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