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