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 @*/
PetscDrawTriangle(PetscDraw draw,PetscReal x1,PetscReal y_1,PetscReal x2,PetscReal y2,PetscReal x3,PetscReal y3,int c1,int c2,int c3)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 @*/
PetscDrawScalePopup(PetscDraw popup,PetscReal min,PetscReal max)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 + ((PetscReal)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
PetscDrawTensorContour_Zoom(PetscDraw win,void * dctx)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 /*@
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 @*/
PetscDrawTensorContour(PetscDraw draw,int m,int n,const PetscReal xi[],const PetscReal yi[],PetscReal v[])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 @*/
PetscDrawTensorContourPatch(PetscDraw draw,int m,int n,PetscReal * x,PetscReal * y,PetscReal min,PetscReal max,PetscReal * v)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