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