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