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