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,n - the global number of mesh points in the x and y directions 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,n - the number of local mesh points in the x and y direction 201 . x - the horizontal locations of the local mesh points 202 . y - the vertical locations of the local mesh points 203 . min - the minimum value in the entire contour 204 . max - the maximum value in the entire contour 205 - v - the data 206 207 Options Database Key: 208 . -draw_x_shared_colormap - Activates private colormap 209 210 Level: advanced 211 212 Note: 213 This is a lower level support routine, usually the user will call 214 `PetscDrawTensorContour()`. 215 216 .seealso: `PetscDraw`, `PetscDrawTensorContour()` 217 @*/ 218 PetscErrorCode PetscDrawTensorContourPatch(PetscDraw draw, int m, int n, PetscReal *x, PetscReal *y, PetscReal min, PetscReal max, PetscReal *v) 219 { 220 int c1, c2, c3, c4, i, j; 221 PetscReal x1, x2, x3, x4, y_1, y2, y3, y4; 222 223 PetscFunctionBegin; 224 PetscValidHeaderSpecific(draw, PETSC_DRAW_CLASSID, 1); 225 /* PetscDraw the contour plot patch */ 226 for (j = 0; j < n - 1; j++) { 227 for (i = 0; i < m - 1; i++) { 228 x1 = x[i]; 229 y_1 = y[j]; 230 c1 = PetscDrawRealToColor(v[i + j * m], min, max); 231 x2 = x[i + 1]; 232 y2 = y_1; 233 c2 = PetscDrawRealToColor(v[i + j * m + 1], min, max); 234 x3 = x2; 235 y3 = y[j + 1]; 236 c3 = PetscDrawRealToColor(v[i + j * m + 1 + m], min, max); 237 x4 = x1; 238 y4 = y3; 239 c4 = PetscDrawRealToColor(v[i + j * m + m], min, max); 240 241 PetscCall(PetscDrawTriangle(draw, x1, y_1, x2, y2, x3, y3, c1, c2, c3)); 242 PetscCall(PetscDrawTriangle(draw, x1, y_1, x3, y3, x4, y4, c1, c3, c4)); 243 } 244 } 245 PetscFunctionReturn(PETSC_SUCCESS); 246 } 247