xref: /petsc/src/sys/classes/draw/interface/dviewp.c (revision feff33ee0b5b037fa8f9f294dede656a2f85cc47)
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,yl,xr,yr - upper right and lower left corners of subwindow
15                  These numbers must always be between 0.0 and 1.0.
16                  Lower left corner is (0,0).
17 -  draw - the drawing context
18 
19    Level: advanced
20 
21    Concepts: drawing^in subset of window
22    Concepts: graphics^in subset of window
23 
24 @*/
25 PetscErrorCode  PetscDrawSetViewPort(PetscDraw draw,PetscReal xl,PetscReal yl,PetscReal xr,PetscReal yr)
26 {
27   PetscErrorCode ierr;
28 
29   PetscFunctionBegin;
30   PetscValidHeaderSpecific(draw,PETSC_DRAW_CLASSID,1);
31   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);
32   draw->port_xl = xl; draw->port_yl = yl;
33   draw->port_xr = xr; draw->port_yr = yr;
34   if (draw->ops->setviewport) {
35     ierr = (*draw->ops->setviewport)(draw,xl,yl,xr,yr);CHKERRQ(ierr);
36   }
37   PetscFunctionReturn(0);
38 }
39 
40 /*@
41    PetscDrawGetViewPort - Gets the portion of the window (page) to which draw
42    routines will write.
43 
44    Collective on PetscDraw
45 
46    Input Parameter:
47 .  draw - the drawing context
48 
49    Output Parameter:
50 .  xl,yl,xr,yr - upper right and lower left corners of subwindow
51                  These numbers must always be between 0.0 and 1.0.
52                  Lower left corner is (0,0).
53 
54    Level: advanced
55 
56    Concepts: drawing^in subset of window
57    Concepts: graphics^in subset of window
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    Concepts: drawing^in subset of window
87 
88 .seealso: PetscDrawDivideViewPort(), PetscDrawSetViewPort()
89 
90 @*/
91 PetscErrorCode  PetscDrawSplitViewPort(PetscDraw draw)
92 {
93   PetscErrorCode ierr;
94   PetscMPIInt    rank,size;
95   PetscInt       n;
96   PetscBool      isnull;
97   PetscReal      xl,xr,yl,yr,h;
98 
99   PetscFunctionBegin;
100   PetscValidHeaderSpecific(draw,PETSC_DRAW_CLASSID,1);
101   ierr = PetscDrawIsNull(draw,&isnull);CHKERRQ(ierr);
102   if (isnull) PetscFunctionReturn(0);
103   ierr = MPI_Comm_rank(PetscObjectComm((PetscObject)draw),&rank);CHKERRQ(ierr);
104   ierr = MPI_Comm_size(PetscObjectComm((PetscObject)draw),&size);CHKERRQ(ierr);
105 
106   n = (PetscInt)(.1 + PetscSqrtReal((PetscReal)size));
107   while (n*n < size) n++;
108 
109   h  = 1.0/n;
110   xl = (rank % n)*h;
111   xr = xl + h;
112   yl = (rank / n)*h;
113   yr = yl + h;
114 
115   ierr = PetscDrawCollectiveBegin(draw);CHKERRQ(ierr);
116   ierr = PetscDrawLine(draw,xl,yl,xl,yr,PETSC_DRAW_BLACK);CHKERRQ(ierr);
117   ierr = PetscDrawLine(draw,xl,yr,xr,yr,PETSC_DRAW_BLACK);CHKERRQ(ierr);
118   ierr = PetscDrawLine(draw,xr,yr,xr,yl,PETSC_DRAW_BLACK);CHKERRQ(ierr);
119   ierr = PetscDrawLine(draw,xr,yl,xl,yl,PETSC_DRAW_BLACK);CHKERRQ(ierr);
120   ierr = PetscDrawCollectiveEnd(draw);CHKERRQ(ierr);
121   ierr = PetscDrawFlush(draw);CHKERRQ(ierr);
122 
123   draw->port_xl = xl + .05*h;
124   draw->port_xr = xr - .05*h;
125   draw->port_yl = yl + .05*h;
126   draw->port_yr = yr - .05*h;
127 
128   if (draw->ops->setviewport) {
129     ierr =  (*draw->ops->setviewport)(draw,xl,yl,xr,yr);CHKERRQ(ierr);
130   }
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 on PetscDraw
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:
147 .  -draw_ports - display multiple fields in the same window with PetscDrawPorts instead of in seperate windows
148 
149    Level: advanced
150 
151    Concepts: drawing^in subset of window
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);CHKERRQ(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) {
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    Concepts: drawing^in subset of window
233 
234 .seealso: PetscDrawSplitViewPort(), PetscDrawSetViewPort(), PetscDrawViewPortsSet(), PetscDrawViewPortsDestroy()
235 
236 @*/
237 PetscErrorCode  PetscDrawViewPortsCreateRect(PetscDraw draw,PetscInt nx,PetscInt ny,PetscDrawViewPorts **newports)
238 {
239   PetscDrawViewPorts *ports;
240   PetscReal          *xl,*xr,*yl,*yr,hx,hy;
241   PetscInt           i,j,k,n;
242   PetscBool          isnull;
243   PetscMPIInt        rank;
244   PetscErrorCode     ierr;
245 
246   PetscFunctionBegin;
247   PetscValidHeaderSpecific(draw,PETSC_DRAW_CLASSID,1);
248   if ((nx < 1) || (ny < 1)) SETERRQ2(PETSC_COMM_SELF,PETSC_ERR_ARG_OUTOFRANGE, "Number of divisions must be positive: %d x %d", nx, ny);
249   PetscValidPointer(newports,3);
250   ierr = PetscDrawIsNull(draw,&isnull);CHKERRQ(ierr);
251   if (isnull) {*newports = NULL; PetscFunctionReturn(0);}
252   ierr = MPI_Comm_rank(PetscObjectComm((PetscObject)draw),&rank);CHKERRQ(ierr);
253 
254   n  = nx*ny;
255   hx = 1.0/nx;
256   hy = 1.0/ny;
257   ierr = PetscNew(&ports);CHKERRQ(ierr); *newports = ports;
258   ports->draw = draw;
259   ports->nports = n;
260   ierr = PetscObjectReference((PetscObject) draw);CHKERRQ(ierr);
261   /* save previous drawport of window */
262   ierr = PetscDrawGetViewPort(draw,&ports->port_xl,&ports->port_yl,&ports->port_xr,&ports->port_yr);CHKERRQ(ierr);
263 
264   ierr = PetscMalloc4(n,&xl,n,&xr,n,&yl,n,&yr);CHKERRQ(ierr);
265   ports->xr = xr;
266   ports->xl = xl;
267   ports->yl = yl;
268   ports->yr = yr;
269 
270   ierr = PetscDrawSetCoordinates(draw,0.0,0.0,1.0,1.0);CHKERRQ(ierr);
271   ierr = PetscDrawCollectiveBegin(draw);CHKERRQ(ierr);
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) {
282         ierr = PetscDrawLine(draw,xl[k],yl[k],xl[k],yr[k],PETSC_DRAW_BLACK);CHKERRQ(ierr);
283         ierr = PetscDrawLine(draw,xl[k],yr[k],xr[k],yr[k],PETSC_DRAW_BLACK);CHKERRQ(ierr);
284         ierr = PetscDrawLine(draw,xr[k],yr[k],xr[k],yl[k],PETSC_DRAW_BLACK);CHKERRQ(ierr);
285         ierr = PetscDrawLine(draw,xr[k],yl[k],xl[k],yl[k],PETSC_DRAW_BLACK);CHKERRQ(ierr);
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   ierr = PetscDrawCollectiveEnd(draw);CHKERRQ(ierr);
295   ierr = PetscDrawFlush(draw);CHKERRQ(ierr);
296   PetscFunctionReturn(0);
297 }
298 
299 /*@C
300    PetscDrawViewPortsDestroy - frees a PetscDrawViewPorts object
301 
302    Collective on PetscDraw inside PetscDrawViewPorts
303 
304    Input Parameter:
305 .  ports - the PetscDrawViewPorts object
306 
307    Level: advanced
308 
309 .seealso: PetscDrawSplitViewPort(), PetscDrawSetViewPort(), PetscDrawViewPortsSet(), PetscDrawViewPortsCreate()
310 
311 @*/
312 PetscErrorCode  PetscDrawViewPortsDestroy(PetscDrawViewPorts *ports)
313 {
314   PetscErrorCode ierr;
315 
316   PetscFunctionBegin;
317   if (!ports) PetscFunctionReturn(0);
318   PetscValidPointer(ports,1);
319   /* reset Drawport of Window back to previous value */
320   ierr = PetscDrawSetViewPort(ports->draw,ports->port_xl,ports->port_yl,ports->port_xr,ports->port_yr);CHKERRQ(ierr);
321   ierr = PetscDrawDestroy(&ports->draw);CHKERRQ(ierr);
322   ierr = PetscFree4(ports->xl,ports->xr,ports->yl,ports->yr);CHKERRQ(ierr);
323   ierr = PetscFree(ports);CHKERRQ(ierr);
324   PetscFunctionReturn(0);
325 }
326 
327 /*@C
328    PetscDrawViewPortsSet - sets a draw object to use a particular subport
329 
330    Logically Collective on PetscDraw inside PetscDrawViewPorts
331 
332    Input Parameter:
333 +  ports - the PetscDrawViewPorts object
334 -  port - the port number, from 0 to nports-1
335 
336    Level: advanced
337 
338    Concepts: drawing^in subset of window
339 
340 .seealso: PetscDrawSplitViewPort(), PetscDrawSetViewPort(), PetscDrawViewPortsDestroy(), PetscDrawViewPortsCreate()
341 
342 @*/
343 PetscErrorCode  PetscDrawViewPortsSet(PetscDrawViewPorts *ports,PetscInt port)
344 {
345   PetscErrorCode ierr;
346 
347   PetscFunctionBegin;
348   if (!ports) PetscFunctionReturn(0);
349   PetscValidPointer(ports,1);
350   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);
351   ierr = PetscDrawSetViewPort(ports->draw,ports->xl[port],ports->yl[port],ports->xr[port],ports->yr[port]);CHKERRQ(ierr);
352   PetscFunctionReturn(0);
353 }
354