xref: /petsc/src/sys/classes/draw/interface/dviewp.c (revision 3f02e49b19195914bf17f317a25cb39636853415)
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 @*/
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 @*/
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 @*/
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 @*/
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 @*/
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 @*/
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 @*/
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