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