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