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