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