xref: /petsc/src/sys/classes/draw/interface/dviewp.c (revision 2fa40bb9206b96114faa7cb222621ec184d31cd2)
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   PetscErrorCode ierr;
30 
31   PetscFunctionBegin;
32   PetscValidHeaderSpecific(draw,PETSC_DRAW_CLASSID,1);
33   if (xl < 0.0 || xr > 1.0 || yl < 0.0 || yr > 1.0 || xr <= xl || yr <= yl) SETERRQ4(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; draw->port_yl = yl;
35   draw->port_xr = xr; draw->port_yr = yr;
36   if (draw->ops->setviewport) {
37     ierr = (*draw->ops->setviewport)(draw,xl,yl,xr,yr);CHKERRQ(ierr);
38   }
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 on PetscDraw
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    Lower left corner is (0,0).
60 
61    Level: advanced
62 
63 @*/
64 PetscErrorCode  PetscDrawGetViewPort(PetscDraw draw,PetscReal *xl,PetscReal *yl,PetscReal *xr,PetscReal *yr)
65 {
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 PetscDraw
84 
85    Input Parameter:
86 .  draw - the drawing context
87 
88    Level: advanced
89 
90 .seealso: PetscDrawDivideViewPort(), PetscDrawSetViewPort()
91 
92 @*/
93 PetscErrorCode  PetscDrawSplitViewPort(PetscDraw draw)
94 {
95   PetscErrorCode ierr;
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   ierr = PetscDrawIsNull(draw,&isnull);CHKERRQ(ierr);
104   if (isnull) PetscFunctionReturn(0);
105   ierr = MPI_Comm_rank(PetscObjectComm((PetscObject)draw),&rank);CHKERRMPI(ierr);
106   ierr = MPI_Comm_size(PetscObjectComm((PetscObject)draw),&size);CHKERRMPI(ierr);
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   ierr = PetscDrawCollectiveBegin(draw);CHKERRQ(ierr);
118   ierr = PetscDrawLine(draw,xl,yl,xl,yr,PETSC_DRAW_BLACK);CHKERRQ(ierr);
119   ierr = PetscDrawLine(draw,xl,yr,xr,yr,PETSC_DRAW_BLACK);CHKERRQ(ierr);
120   ierr = PetscDrawLine(draw,xr,yr,xr,yl,PETSC_DRAW_BLACK);CHKERRQ(ierr);
121   ierr = PetscDrawLine(draw,xr,yl,xl,yl,PETSC_DRAW_BLACK);CHKERRQ(ierr);
122   ierr = PetscDrawCollectiveEnd(draw);CHKERRQ(ierr);
123   ierr = PetscDrawFlush(draw);CHKERRQ(ierr);
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   if (draw->ops->setviewport) {
131     ierr =  (*draw->ops->setviewport)(draw,xl,yl,xr,yr);CHKERRQ(ierr);
132   }
133   PetscFunctionReturn(0);
134 }
135 
136 /*@C
137    PetscDrawViewPortsCreate - Splits a window into smaller view ports. Each processor shares all the viewports.
138 
139    Collective on PetscDraw
140 
141    Input Parameters:
142 +  draw - the drawing context
143 -  nports - the number of ports
144 
145    Output Parameter:
146 .  ports - a PetscDrawViewPorts context (C structure)
147 
148    Options Database:
149 .  -draw_ports - display multiple fields in the same window with PetscDrawPorts instead of in separate windows
150 
151    Level: advanced
152 
153 .seealso: PetscDrawSplitViewPort(), PetscDrawSetViewPort(), PetscDrawViewPortsSet(), PetscDrawViewPortsDestroy()
154 
155 @*/
156 PetscErrorCode  PetscDrawViewPortsCreate(PetscDraw draw,PetscInt nports,PetscDrawViewPorts **newports)
157 {
158   PetscDrawViewPorts *ports;
159   PetscInt           i,n;
160   PetscBool          isnull;
161   PetscMPIInt        rank;
162   PetscReal          *xl,*xr,*yl,*yr,h;
163   PetscErrorCode     ierr;
164 
165   PetscFunctionBegin;
166   PetscValidHeaderSpecific(draw,PETSC_DRAW_CLASSID,1);
167   if (nports < 1) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_ARG_OUTOFRANGE, "Number of divisions must be positive: %d", nports);
168   PetscValidPointer(newports,3);
169   ierr = PetscDrawIsNull(draw,&isnull);CHKERRQ(ierr);
170   if (isnull) {*newports = NULL; PetscFunctionReturn(0);}
171   ierr = MPI_Comm_rank(PetscObjectComm((PetscObject)draw),&rank);CHKERRMPI(ierr);
172 
173   ierr = PetscNew(&ports);CHKERRQ(ierr); *newports = ports;
174   ports->draw = draw;
175   ports->nports = nports;
176   ierr = PetscObjectReference((PetscObject)draw);CHKERRQ(ierr);
177   /* save previous drawport of window */
178   ierr = PetscDrawGetViewPort(draw,&ports->port_xl,&ports->port_yl,&ports->port_xr,&ports->port_yr);CHKERRQ(ierr);
179 
180   n = (PetscInt)(.1 + PetscSqrtReal((PetscReal)nports));
181   while (n*n < nports) n++;
182   h = 1.0/n;
183 
184   ierr = PetscMalloc4(n*n,&xl,n*n,&xr,n*n,&yl,n*n,&yr);CHKERRQ(ierr);
185   ports->xl = xl;
186   ports->xr = xr;
187   ports->yl = yl;
188   ports->yr = yr;
189 
190   ierr = PetscDrawSetCoordinates(draw,0.0,0.0,1.0,1.0);CHKERRQ(ierr);
191   ierr = PetscDrawCollectiveBegin(draw);CHKERRQ(ierr);
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       ierr = PetscDrawLine(draw,xl[i],yl[i],xl[i],yr[i],PETSC_DRAW_BLACK);CHKERRQ(ierr);
200       ierr = PetscDrawLine(draw,xl[i],yr[i],xr[i],yr[i],PETSC_DRAW_BLACK);CHKERRQ(ierr);
201       ierr = PetscDrawLine(draw,xr[i],yr[i],xr[i],yl[i],PETSC_DRAW_BLACK);CHKERRQ(ierr);
202       ierr = PetscDrawLine(draw,xr[i],yl[i],xl[i],yl[i],PETSC_DRAW_BLACK);CHKERRQ(ierr);
203     }
204 
205     xl[i] += .05*h;
206     xr[i] -= .05*h;
207     yl[i] += .05*h;
208     yr[i] -= .05*h;
209   }
210   ierr = PetscDrawCollectiveEnd(draw);CHKERRQ(ierr);
211   ierr = PetscDrawFlush(draw);CHKERRQ(ierr);
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 on PetscDraw
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()
233 
234 @*/
235 PetscErrorCode  PetscDrawViewPortsCreateRect(PetscDraw draw,PetscInt nx,PetscInt ny,PetscDrawViewPorts **newports)
236 {
237   PetscDrawViewPorts *ports;
238   PetscReal          *xl,*xr,*yl,*yr,hx,hy;
239   PetscInt           i,j,k,n;
240   PetscBool          isnull;
241   PetscMPIInt        rank;
242   PetscErrorCode     ierr;
243 
244   PetscFunctionBegin;
245   PetscValidHeaderSpecific(draw,PETSC_DRAW_CLASSID,1);
246   if ((nx < 1) || (ny < 1)) SETERRQ2(PETSC_COMM_SELF,PETSC_ERR_ARG_OUTOFRANGE, "Number of divisions must be positive: %d x %d", nx, ny);
247   PetscValidPointer(newports,4);
248   ierr = PetscDrawIsNull(draw,&isnull);CHKERRQ(ierr);
249   if (isnull) {*newports = NULL; PetscFunctionReturn(0);}
250   ierr = MPI_Comm_rank(PetscObjectComm((PetscObject)draw),&rank);CHKERRMPI(ierr);
251 
252   n  = nx*ny;
253   hx = 1.0/nx;
254   hy = 1.0/ny;
255   ierr = PetscNew(&ports);CHKERRQ(ierr); *newports = ports;
256   ports->draw = draw;
257   ports->nports = n;
258   ierr = PetscObjectReference((PetscObject) draw);CHKERRQ(ierr);
259   /* save previous drawport of window */
260   ierr = PetscDrawGetViewPort(draw,&ports->port_xl,&ports->port_yl,&ports->port_xr,&ports->port_yr);CHKERRQ(ierr);
261 
262   ierr = PetscMalloc4(n,&xl,n,&xr,n,&yl,n,&yr);CHKERRQ(ierr);
263   ports->xr = xr;
264   ports->xl = xl;
265   ports->yl = yl;
266   ports->yr = yr;
267 
268   ierr = PetscDrawSetCoordinates(draw,0.0,0.0,1.0,1.0);CHKERRQ(ierr);
269   ierr = PetscDrawCollectiveBegin(draw);CHKERRQ(ierr);
270   for (i = 0; i < nx; i++) {
271     for (j = 0; j < ny; j++) {
272       k = j*nx+i;
273 
274       xl[k] = i*hx;
275       xr[k] = xl[k] + hx;
276       yl[k] = j*hy;
277       yr[k] = yl[k] + hy;
278 
279       if (rank == 0) {
280         ierr = PetscDrawLine(draw,xl[k],yl[k],xl[k],yr[k],PETSC_DRAW_BLACK);CHKERRQ(ierr);
281         ierr = PetscDrawLine(draw,xl[k],yr[k],xr[k],yr[k],PETSC_DRAW_BLACK);CHKERRQ(ierr);
282         ierr = PetscDrawLine(draw,xr[k],yr[k],xr[k],yl[k],PETSC_DRAW_BLACK);CHKERRQ(ierr);
283         ierr = PetscDrawLine(draw,xr[k],yl[k],xl[k],yl[k],PETSC_DRAW_BLACK);CHKERRQ(ierr);
284       }
285 
286       xl[k] += .05*hx;
287       xr[k] -= .05*hx;
288       yl[k] += .05*hy;
289       yr[k] -= .05*hy;
290     }
291   }
292   ierr = PetscDrawCollectiveEnd(draw);CHKERRQ(ierr);
293   ierr = PetscDrawFlush(draw);CHKERRQ(ierr);
294   PetscFunctionReturn(0);
295 }
296 
297 /*@C
298    PetscDrawViewPortsDestroy - frees a PetscDrawViewPorts object
299 
300    Collective on PetscDraw inside PetscDrawViewPorts
301 
302    Input Parameter:
303 .  ports - the PetscDrawViewPorts object
304 
305    Level: advanced
306 
307 .seealso: PetscDrawSplitViewPort(), PetscDrawSetViewPort(), PetscDrawViewPortsSet(), PetscDrawViewPortsCreate()
308 
309 @*/
310 PetscErrorCode  PetscDrawViewPortsDestroy(PetscDrawViewPorts *ports)
311 {
312   PetscErrorCode ierr;
313 
314   PetscFunctionBegin;
315   if (!ports) PetscFunctionReturn(0);
316   PetscValidPointer(ports,1);
317   /* reset Drawport of Window back to previous value */
318   ierr = PetscDrawSetViewPort(ports->draw,ports->port_xl,ports->port_yl,ports->port_xr,ports->port_yr);CHKERRQ(ierr);
319   ierr = PetscDrawDestroy(&ports->draw);CHKERRQ(ierr);
320   ierr = PetscFree4(ports->xl,ports->xr,ports->yl,ports->yr);CHKERRQ(ierr);
321   ierr = PetscFree(ports);CHKERRQ(ierr);
322   PetscFunctionReturn(0);
323 }
324 
325 /*@C
326    PetscDrawViewPortsSet - sets a draw object to use a particular subport
327 
328    Logically Collective on PetscDraw inside PetscDrawViewPorts
329 
330    Input Parameters:
331 +  ports - the PetscDrawViewPorts object
332 -  port - the port number, from 0 to nports-1
333 
334    Level: advanced
335 
336 .seealso: PetscDrawSplitViewPort(), PetscDrawSetViewPort(), PetscDrawViewPortsDestroy(), PetscDrawViewPortsCreate()
337 
338 @*/
339 PetscErrorCode  PetscDrawViewPortsSet(PetscDrawViewPorts *ports,PetscInt port)
340 {
341   PetscErrorCode ierr;
342 
343   PetscFunctionBegin;
344   if (!ports) PetscFunctionReturn(0);
345   PetscValidPointer(ports,1);
346   if (port < 0 || port > ports->nports-1) SETERRQ2(PETSC_COMM_SELF,PETSC_ERR_ARG_OUTOFRANGE,"Port is out of range requested %d from 0 to %d\n",port,ports->nports-1);
347   ierr = PetscDrawSetViewPort(ports->draw,ports->xl[port],ports->yl[port],ports->xr[port],ports->yr[port]);CHKERRQ(ierr);
348   PetscFunctionReturn(0);
349 }
350