1 #include <petsc/private/drawimpl.h> /*I "petscdraw.h" I*/
2
3 /*@
4 PetscDrawSetViewPort - Sets the portion of the window (page) to which draw
5 routines will write.
6
7 Collective
8
9 Input Parameters:
10 + xl - the horizontal coordinate of the lower left corner of the subwindow.
11 . yl - the vertical coordinate of the lower left corner of the subwindow.
12 . xr - the horizontal coordinate of the upper right corner of the subwindow.
13 . yr - the vertical coordinate of the upper right corner of the subwindow.
14 - draw - the drawing context
15
16 Level: advanced
17
18 Notes:
19 These numbers must always be between 0.0 and 1.0.
20
21 Lower left corner is (0,0).
22
23 .seealso: `PetscDrawGetViewPort()`, `PetscDraw`, `PetscDrawSplitViewPort()`, `PetscDrawViewPortsCreate()`
24 @*/
PetscDrawSetViewPort(PetscDraw draw,PetscReal xl,PetscReal yl,PetscReal xr,PetscReal yr)25 PetscErrorCode PetscDrawSetViewPort(PetscDraw draw, PetscReal xl, PetscReal yl, PetscReal xr, PetscReal yr)
26 {
27 PetscFunctionBegin;
28 PetscValidHeaderSpecific(draw, PETSC_DRAW_CLASSID, 1);
29 PetscCheck(xl >= 0.0 && xr <= 1.0 && yl >= 0.0 && yr <= 1.0 && xr > xl && yr > yl, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "ViewPort values must be >= 0 and <= 1: Instead %g %g %g %g", (double)xl, (double)yl, (double)xr, (double)yr);
30 draw->port_xl = xl;
31 draw->port_yl = yl;
32 draw->port_xr = xr;
33 draw->port_yr = yr;
34 PetscTryTypeMethod(draw, setviewport, xl, yl, xr, yr);
35 PetscFunctionReturn(PETSC_SUCCESS);
36 }
37
38 /*@
39 PetscDrawGetViewPort - Gets the portion of the window (page) to which draw
40 routines will write.
41
42 Collective
43
44 Input Parameter:
45 . draw - the drawing context
46
47 Output Parameters:
48 + xl - the horizontal coordinate of the lower left corner of the subwindow.
49 . yl - the vertical coordinate of the lower left corner of the subwindow.
50 . xr - the horizontal coordinate of the upper right corner of the subwindow.
51 - yr - the vertical coordinate of the upper right corner of the subwindow.
52
53 Level: advanced
54
55 Notes:
56 These numbers must always be between 0.0 and 1.0.
57
58 Lower left corner is (0,0).
59
60 .seealso: `PetscDraw`, `PetscDrawSplitViewPort()`, `PetscDrawSetViewPort()`
61 @*/
PetscDrawGetViewPort(PetscDraw draw,PetscReal * xl,PetscReal * yl,PetscReal * xr,PetscReal * yr)62 PetscErrorCode PetscDrawGetViewPort(PetscDraw draw, PetscReal *xl, PetscReal *yl, PetscReal *xr, PetscReal *yr)
63 {
64 PetscFunctionBegin;
65 PetscValidHeaderSpecific(draw, PETSC_DRAW_CLASSID, 1);
66 PetscAssertPointer(xl, 2);
67 PetscAssertPointer(yl, 3);
68 PetscAssertPointer(xr, 4);
69 PetscAssertPointer(yr, 5);
70 *xl = draw->port_xl;
71 *yl = draw->port_yl;
72 *xr = draw->port_xr;
73 *yr = draw->port_yr;
74 PetscFunctionReturn(PETSC_SUCCESS);
75 }
76
77 /*@
78 PetscDrawSplitViewPort - Splits a window shared by several processes into smaller
79 view ports. One for each process.
80
81 Collective
82
83 Input Parameter:
84 . draw - the drawing context
85
86 Level: advanced
87
88 .seealso: `PetscDrawDivideViewPort()`, `PetscDrawSetViewPort()`
89 @*/
PetscDrawSplitViewPort(PetscDraw draw)90 PetscErrorCode PetscDrawSplitViewPort(PetscDraw draw)
91 {
92 PetscMPIInt rank, size;
93 PetscInt n;
94 PetscBool isnull;
95 PetscReal xl, xr, yl, yr, h;
96
97 PetscFunctionBegin;
98 PetscValidHeaderSpecific(draw, PETSC_DRAW_CLASSID, 1);
99 PetscCall(PetscDrawIsNull(draw, &isnull));
100 if (isnull) PetscFunctionReturn(PETSC_SUCCESS);
101 PetscCallMPI(MPI_Comm_rank(PetscObjectComm((PetscObject)draw), &rank));
102 PetscCallMPI(MPI_Comm_size(PetscObjectComm((PetscObject)draw), &size));
103
104 n = (PetscInt)(.1 + PetscSqrtReal((PetscReal)size));
105 while (n * n < size) n++;
106
107 h = 1.0 / (PetscReal)n;
108 xl = ((PetscReal)(rank % n)) * h;
109 xr = xl + h;
110 yl = ((PetscReal)(rank / n)) * h;
111 yr = yl + h;
112
113 PetscDrawCollectiveBegin(draw);
114 PetscCall(PetscDrawLine(draw, xl, yl, xl, yr, PETSC_DRAW_BLACK));
115 PetscCall(PetscDrawLine(draw, xl, yr, xr, yr, PETSC_DRAW_BLACK));
116 PetscCall(PetscDrawLine(draw, xr, yr, xr, yl, PETSC_DRAW_BLACK));
117 PetscCall(PetscDrawLine(draw, xr, yl, xl, yl, PETSC_DRAW_BLACK));
118 PetscDrawCollectiveEnd(draw);
119 PetscCall(PetscDrawFlush(draw));
120
121 draw->port_xl = xl + .05 * h;
122 draw->port_xr = xr - .05 * h;
123 draw->port_yl = yl + .05 * h;
124 draw->port_yr = yr - .05 * h;
125
126 PetscTryTypeMethod(draw, setviewport, xl, yl, xr, yr);
127 PetscFunctionReturn(PETSC_SUCCESS);
128 }
129
130 /*@C
131 PetscDrawViewPortsCreate - Splits a window into smaller view ports. Each processor shares all the viewports.
132
133 Collective
134
135 Input Parameters:
136 + draw - the drawing context
137 - nports - the number of ports
138
139 Output Parameter:
140 . newports - a `PetscDrawViewPorts` context (C structure)
141
142 Options Database Key:
143 . -draw_ports - display multiple fields in the same window with PetscDrawPorts() instead of in separate windows
144
145 Level: advanced
146
147 Fortran Note:
148 No Fortran support since `PetscDrawViewPorts` is a C struct
149
150 .seealso: `PetscDrawSplitViewPort()`, `PetscDrawSetViewPort()`, `PetscDrawViewPortsSet()`, `PetscDrawViewPortsDestroy()`
151 @*/
PetscDrawViewPortsCreate(PetscDraw draw,PetscInt nports,PetscDrawViewPorts * newports[])152 PetscErrorCode PetscDrawViewPortsCreate(PetscDraw draw, PetscInt nports, PetscDrawViewPorts *newports[])
153 {
154 PetscDrawViewPorts *ports;
155 PetscInt i, n;
156 PetscBool isnull;
157 PetscMPIInt rank;
158 PetscReal *xl, *xr, *yl, *yr, h;
159
160 PetscFunctionBegin;
161 PetscValidHeaderSpecific(draw, PETSC_DRAW_CLASSID, 1);
162 PetscCheck(nports >= 1, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Number of divisions must be positive: %" PetscInt_FMT, nports);
163 PetscAssertPointer(newports, 3);
164 PetscCall(PetscDrawIsNull(draw, &isnull));
165 if (isnull) {
166 *newports = NULL;
167 PetscFunctionReturn(PETSC_SUCCESS);
168 }
169 PetscCallMPI(MPI_Comm_rank(PetscObjectComm((PetscObject)draw), &rank));
170
171 PetscCall(PetscNew(&ports));
172 *newports = ports;
173 ports->draw = draw;
174 ports->nports = nports;
175 PetscCall(PetscObjectReference((PetscObject)draw));
176 /* save previous drawport of window */
177 PetscCall(PetscDrawGetViewPort(draw, &ports->port_xl, &ports->port_yl, &ports->port_xr, &ports->port_yr));
178
179 n = (PetscInt)(.1 + PetscSqrtReal((PetscReal)nports));
180 while (n * n < nports) n++;
181 h = 1.0 / (PetscReal)n;
182
183 PetscCall(PetscMalloc4(n * n, &xl, n * n, &xr, n * n, &yl, n * n, &yr));
184 ports->xl = xl;
185 ports->xr = xr;
186 ports->yl = yl;
187 ports->yr = yr;
188
189 PetscCall(PetscDrawSetCoordinates(draw, 0.0, 0.0, 1.0, 1.0));
190 PetscDrawCollectiveBegin(draw);
191 for (i = 0; i < n * n; i++) {
192 xl[i] = ((PetscReal)(i % n)) * h;
193 xr[i] = xl[i] + h;
194 yl[i] = ((PetscReal)(i / n)) * h;
195 yr[i] = yl[i] + h;
196
197 if (rank == 0) {
198 PetscCall(PetscDrawLine(draw, xl[i], yl[i], xl[i], yr[i], PETSC_DRAW_BLACK));
199 PetscCall(PetscDrawLine(draw, xl[i], yr[i], xr[i], yr[i], PETSC_DRAW_BLACK));
200 PetscCall(PetscDrawLine(draw, xr[i], yr[i], xr[i], yl[i], PETSC_DRAW_BLACK));
201 PetscCall(PetscDrawLine(draw, xr[i], yl[i], xl[i], yl[i], PETSC_DRAW_BLACK));
202 }
203
204 xl[i] += .05 * h;
205 xr[i] -= .05 * h;
206 yl[i] += .05 * h;
207 yr[i] -= .05 * h;
208 }
209 PetscDrawCollectiveEnd(draw);
210 PetscCall(PetscDrawFlush(draw));
211 PetscFunctionReturn(PETSC_SUCCESS);
212 }
213
214 /*@C
215 PetscDrawViewPortsCreateRect - Splits a window into smaller
216 view ports. Each processor shares all the viewports. The number
217 of views in the x- and y-directions is specified.
218
219 Collective
220
221 Input Parameters:
222 + draw - the drawing context
223 . nx - the number of x divisions
224 - ny - the number of y divisions
225
226 Output Parameter:
227 . newports - a `PetscDrawViewPorts` context (C structure)
228
229 Level: advanced
230
231 Fortran Note:
232 No Fortran support
233
234 .seealso: `PetscDrawSplitViewPort()`, `PetscDrawSetViewPort()`, `PetscDrawViewPortsSet()`, `PetscDrawViewPortsDestroy()`, `PetscDrawViewPorts`
235 @*/
PetscDrawViewPortsCreateRect(PetscDraw draw,PetscInt nx,PetscInt ny,PetscDrawViewPorts * newports[])236 PetscErrorCode PetscDrawViewPortsCreateRect(PetscDraw draw, PetscInt nx, PetscInt ny, PetscDrawViewPorts *newports[])
237 {
238 PetscDrawViewPorts *ports;
239 PetscReal *xl, *xr, *yl, *yr, hx, hy;
240 PetscInt i, j, k, n;
241 PetscBool isnull;
242 PetscMPIInt rank;
243
244 PetscFunctionBegin;
245 PetscValidHeaderSpecific(draw, PETSC_DRAW_CLASSID, 1);
246 PetscCheck(nx >= 1 && ny >= 1, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Number of divisions must be positive: %" PetscInt_FMT " x %" PetscInt_FMT, nx, ny);
247 PetscAssertPointer(newports, 4);
248 PetscCall(PetscDrawIsNull(draw, &isnull));
249 if (isnull) {
250 *newports = NULL;
251 PetscFunctionReturn(PETSC_SUCCESS);
252 }
253 PetscCallMPI(MPI_Comm_rank(PetscObjectComm((PetscObject)draw), &rank));
254
255 n = nx * ny;
256 hx = 1.0 / (PetscReal)nx;
257 hy = 1.0 / (PetscReal)ny;
258 PetscCall(PetscNew(&ports));
259 *newports = ports;
260 ports->draw = draw;
261 ports->nports = n;
262 PetscCall(PetscObjectReference((PetscObject)draw));
263 /* save previous drawport of window */
264 PetscCall(PetscDrawGetViewPort(draw, &ports->port_xl, &ports->port_yl, &ports->port_xr, &ports->port_yr));
265
266 PetscCall(PetscMalloc4(n, &xl, n, &xr, n, &yl, n, &yr));
267 ports->xr = xr;
268 ports->xl = xl;
269 ports->yl = yl;
270 ports->yr = yr;
271
272 PetscCall(PetscDrawSetCoordinates(draw, 0.0, 0.0, 1.0, 1.0));
273 PetscDrawCollectiveBegin(draw);
274 for (i = 0; i < nx; i++) {
275 for (j = 0; j < ny; j++) {
276 k = j * nx + i;
277
278 xl[k] = ((PetscReal)i) * hx;
279 xr[k] = xl[k] + hx;
280 yl[k] = ((PetscReal)j) * hy;
281 yr[k] = yl[k] + hy;
282
283 if (rank == 0) {
284 PetscCall(PetscDrawLine(draw, xl[k], yl[k], xl[k], yr[k], PETSC_DRAW_BLACK));
285 PetscCall(PetscDrawLine(draw, xl[k], yr[k], xr[k], yr[k], PETSC_DRAW_BLACK));
286 PetscCall(PetscDrawLine(draw, xr[k], yr[k], xr[k], yl[k], PETSC_DRAW_BLACK));
287 PetscCall(PetscDrawLine(draw, xr[k], yl[k], xl[k], yl[k], PETSC_DRAW_BLACK));
288 }
289
290 xl[k] += .05 * hx;
291 xr[k] -= .05 * hx;
292 yl[k] += .05 * hy;
293 yr[k] -= .05 * hy;
294 }
295 }
296 PetscDrawCollectiveEnd(draw);
297 PetscCall(PetscDrawFlush(draw));
298 PetscFunctionReturn(PETSC_SUCCESS);
299 }
300
301 /*@C
302 PetscDrawViewPortsDestroy - frees a `PetscDrawViewPorts` object
303
304 Collective on the `PetscDraw` inside `ports`
305
306 Input Parameter:
307 . ports - the `PetscDrawViewPorts` object
308
309 Level: advanced
310
311 Fortran Note:
312 No Fortran support
313
314 .seealso: `PetscDrawViewPorts`, `PetscDrawSplitViewPort()`, `PetscDrawSetViewPort()`, `PetscDrawViewPortsSet()`, `PetscDrawViewPortsCreate()`
315 @*/
PetscDrawViewPortsDestroy(PetscDrawViewPorts * ports)316 PetscErrorCode PetscDrawViewPortsDestroy(PetscDrawViewPorts *ports)
317 {
318 PetscFunctionBegin;
319 if (!ports) PetscFunctionReturn(PETSC_SUCCESS);
320 PetscAssertPointer(ports, 1);
321 /* reset Drawport of Window back to previous value */
322 PetscCall(PetscDrawSetViewPort(ports->draw, ports->port_xl, ports->port_yl, ports->port_xr, ports->port_yr));
323 PetscCall(PetscDrawDestroy(&ports->draw));
324 PetscCall(PetscFree4(ports->xl, ports->xr, ports->yl, ports->yr));
325 PetscCall(PetscFree(ports));
326 PetscFunctionReturn(PETSC_SUCCESS);
327 }
328
329 /*@C
330 PetscDrawViewPortsSet - sets a draw object to use a particular subport
331
332 Logically Collective on the `PetscDraw` inside `ports`
333
334 Input Parameters:
335 + ports - the `PetscDrawViewPorts` object
336 - port - the port number, from 0 to nports-1
337
338 Level: advanced
339
340 Fortran Note:
341 No Fortran support
342
343 .seealso: `PetscDrawViewPorts`, `PetscDrawSplitViewPort()`, `PetscDrawSetViewPort()`, `PetscDrawViewPortsDestroy()`, `PetscDrawViewPortsCreate()`
344 @*/
PetscDrawViewPortsSet(PetscDrawViewPorts * ports,PetscInt port)345 PetscErrorCode PetscDrawViewPortsSet(PetscDrawViewPorts *ports, PetscInt port)
346 {
347 PetscFunctionBegin;
348 if (!ports) PetscFunctionReturn(PETSC_SUCCESS);
349 PetscAssertPointer(ports, 1);
350 PetscCheck(port >= 0 && (port <= ports->nports - 1), PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Port is out of range requested %" PetscInt_FMT " from 0 to %" PetscInt_FMT, port, ports->nports - 1);
351 PetscCall(PetscDrawSetViewPort(ports->draw, ports->xl[port], ports->yl[port], ports->xr[port], ports->yr[port]));
352 PetscFunctionReturn(PETSC_SUCCESS);
353 }
354