xref: /petsc/src/sys/classes/viewer/impls/draw/drawv.c (revision 6a98f8dc3f2c9149905a87dc2e9d0fedaf64e09a)
1 
2 #include <../src/sys/classes/viewer/impls/draw/vdraw.h> /*I "petscdraw.h" I*/
3 #include <petscviewer.h>                                /*I "petscviewer.h" I*/
4 
5 static PetscErrorCode PetscViewerDestroy_Draw(PetscViewer v)
6 {
7   PetscErrorCode   ierr;
8   PetscInt         i;
9   PetscViewer_Draw *vdraw = (PetscViewer_Draw*)v->data;
10 
11   PetscFunctionBegin;
12   if (vdraw->singleton_made) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ORDER,"Destroying PetscViewer without first restoring singleton");
13   for (i=0; i<vdraw->draw_max; i++) {
14     ierr = PetscDrawAxisDestroy(&vdraw->drawaxis[i]);CHKERRQ(ierr);
15     ierr = PetscDrawLGDestroy(&vdraw->drawlg[i]);CHKERRQ(ierr);
16     ierr = PetscDrawDestroy(&vdraw->draw[i]);CHKERRQ(ierr);
17   }
18   ierr = PetscFree(vdraw->display);CHKERRQ(ierr);
19   ierr = PetscFree(vdraw->title);CHKERRQ(ierr);
20   ierr = PetscFree3(vdraw->draw,vdraw->drawlg,vdraw->drawaxis);CHKERRQ(ierr);
21   ierr = PetscFree(vdraw->bounds);CHKERRQ(ierr);
22   ierr = PetscFree(vdraw->drawtype);CHKERRQ(ierr);
23   ierr = PetscFree(v->data);CHKERRQ(ierr);
24   PetscFunctionReturn(0);
25 }
26 
27 static PetscErrorCode PetscViewerFlush_Draw(PetscViewer v)
28 {
29   PetscErrorCode   ierr;
30   PetscInt         i;
31   PetscViewer_Draw *vdraw = (PetscViewer_Draw*)v->data;
32 
33   PetscFunctionBegin;
34   for (i=0; i<vdraw->draw_max; i++) {
35     if (vdraw->draw[i]) {ierr = PetscDrawFlush(vdraw->draw[i]);CHKERRQ(ierr);}
36   }
37   PetscFunctionReturn(0);
38 }
39 
40 /*@C
41     PetscViewerDrawGetDraw - Returns PetscDraw object from PetscViewer object.
42     This PetscDraw object may then be used to perform graphics using
43     PetscDrawXXX() commands.
44 
45     Collective on PetscViewer
46 
47     Input Parameters:
48 +   viewer - the PetscViewer (created with PetscViewerDrawOpen())
49 -   windownumber - indicates which subwindow (usually 0)
50 
51     Ouput Parameter:
52 .   draw - the draw object
53 
54     Level: intermediate
55 
56 
57 .seealso: PetscViewerDrawGetLG(), PetscViewerDrawGetAxis(), PetscViewerDrawOpen()
58 @*/
59 PetscErrorCode  PetscViewerDrawGetDraw(PetscViewer viewer,PetscInt windownumber,PetscDraw *draw)
60 {
61   PetscViewer_Draw *vdraw;
62   PetscErrorCode   ierr;
63   PetscBool        isdraw;
64 
65   PetscFunctionBegin;
66   PetscValidHeaderSpecific(viewer,PETSC_VIEWER_CLASSID,1);
67   PetscValidLogicalCollectiveInt(viewer,windownumber,2);
68   if (draw) PetscValidPointer(draw,3);
69   ierr = PetscObjectTypeCompare((PetscObject)viewer,PETSCVIEWERDRAW,&isdraw);CHKERRQ(ierr);
70   if (!isdraw) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_WRONG,"Must be draw type PetscViewer");
71   if (windownumber < 0) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_OUTOFRANGE,"Window number cannot be negative");
72   vdraw = (PetscViewer_Draw*)viewer->data;
73 
74   windownumber += vdraw->draw_base;
75   if (windownumber >= vdraw->draw_max) {
76     /* allocate twice as many slots as needed */
77     PetscInt      draw_max  = vdraw->draw_max;
78     PetscDraw     *tdraw    = vdraw->draw;
79     PetscDrawLG   *drawlg   = vdraw->drawlg;
80     PetscDrawAxis *drawaxis = vdraw->drawaxis;
81 
82     vdraw->draw_max = 2*windownumber;
83 
84     ierr = PetscCalloc3(vdraw->draw_max,&vdraw->draw,vdraw->draw_max,&vdraw->drawlg,vdraw->draw_max,&vdraw->drawaxis);CHKERRQ(ierr);
85     ierr = PetscArraycpy(vdraw->draw,tdraw,draw_max);CHKERRQ(ierr);
86     ierr = PetscArraycpy(vdraw->drawlg,drawlg,draw_max);CHKERRQ(ierr);
87     ierr = PetscArraycpy(vdraw->drawaxis,drawaxis,draw_max);CHKERRQ(ierr);
88     ierr = PetscFree3(tdraw,drawlg,drawaxis);CHKERRQ(ierr);
89   }
90 
91   if (!vdraw->draw[windownumber]) {
92     char *title = vdraw->title, tmp_str[128];
93     if (windownumber) {
94       ierr = PetscSNPrintf(tmp_str,sizeof(tmp_str),"%s:%d",vdraw->title?vdraw->title:"",windownumber);CHKERRQ(ierr);
95       title = tmp_str;
96     }
97     ierr = PetscDrawCreate(PetscObjectComm((PetscObject)viewer),vdraw->display,title,PETSC_DECIDE,PETSC_DECIDE,vdraw->w,vdraw->h,&vdraw->draw[windownumber]);CHKERRQ(ierr);
98     ierr = PetscLogObjectParent((PetscObject)viewer,(PetscObject)vdraw->draw[windownumber]);CHKERRQ(ierr);
99     if (vdraw->drawtype) {
100       ierr = PetscDrawSetType(vdraw->draw[windownumber],vdraw->drawtype);CHKERRQ(ierr);
101     }
102     ierr = PetscDrawSetPause(vdraw->draw[windownumber],vdraw->pause);CHKERRQ(ierr);
103     ierr = PetscDrawSetOptionsPrefix(vdraw->draw[windownumber],((PetscObject)viewer)->prefix);CHKERRQ(ierr);
104     ierr = PetscDrawSetFromOptions(vdraw->draw[windownumber]);CHKERRQ(ierr);
105   }
106   if (draw) *draw = vdraw->draw[windownumber];
107   if (draw) PetscValidHeaderSpecific(*draw,PETSC_DRAW_CLASSID,-1);
108   PetscFunctionReturn(0);
109 }
110 
111 /*@C
112     PetscViewerDrawBaseAdd - add to the base integer that is added to the windownumber passed to PetscViewerDrawGetDraw()
113 
114     Logically Collective on PetscViewer
115 
116     Input Parameters:
117 +  viewer - the PetscViewer (created with PetscViewerDrawOpen())
118 -   windownumber - how much to add to the base
119 
120     Level: developer
121 
122 
123 .seealso: PetscViewerDrawGetLG(), PetscViewerDrawGetAxis(), PetscViewerDrawOpen(), PetscViewerDrawGetDraw(), PetscViewerDrawBaseSet()
124 @*/
125 PetscErrorCode  PetscViewerDrawBaseAdd(PetscViewer viewer,PetscInt windownumber)
126 {
127   PetscViewer_Draw *vdraw;
128   PetscErrorCode   ierr;
129   PetscBool        isdraw;
130 
131   PetscFunctionBegin;
132   PetscValidHeaderSpecific(viewer,PETSC_VIEWER_CLASSID,1);
133   PetscValidLogicalCollectiveInt(viewer,windownumber,2);
134   ierr = PetscObjectTypeCompare((PetscObject)viewer,PETSCVIEWERDRAW,&isdraw);CHKERRQ(ierr);
135   if (!isdraw) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_WRONG,"Must be draw type PetscViewer");
136   vdraw = (PetscViewer_Draw*)viewer->data;
137 
138   if (windownumber + vdraw->draw_base < 0) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_ARG_OUTOFRANGE,"Resulting base %D cannot be negative",windownumber+vdraw->draw_base);
139   vdraw->draw_base += windownumber;
140   PetscFunctionReturn(0);
141 }
142 
143 /*@C
144     PetscViewerDrawBaseSet - sets the base integer that is added to the windownumber passed to PetscViewerDrawGetDraw()
145 
146     Logically Collective on PetscViewer
147 
148     Input Parameters:
149 +   viewer - the PetscViewer (created with PetscViewerDrawOpen())
150 -   windownumber - value to set the base
151 
152     Level: developer
153 
154 
155 .seealso: PetscViewerDrawGetLG(), PetscViewerDrawGetAxis(), PetscViewerDrawOpen(), PetscViewerDrawGetDraw(), PetscViewerDrawBaseAdd()
156 @*/
157 PetscErrorCode  PetscViewerDrawBaseSet(PetscViewer viewer,PetscInt windownumber)
158 {
159   PetscViewer_Draw *vdraw;
160   PetscErrorCode   ierr;
161   PetscBool        isdraw;
162 
163   PetscFunctionBegin;
164   PetscValidHeaderSpecific(viewer,PETSC_VIEWER_CLASSID,1);
165   PetscValidLogicalCollectiveInt(viewer,windownumber,2);
166   ierr = PetscObjectTypeCompare((PetscObject)viewer,PETSCVIEWERDRAW,&isdraw);CHKERRQ(ierr);
167   if (!isdraw) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_WRONG,"Must be draw type PetscViewer");
168   vdraw = (PetscViewer_Draw*)viewer->data;
169 
170   if (windownumber < 0) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_ARG_OUTOFRANGE,"Resulting base %D cannot be negative",windownumber);
171   vdraw->draw_base = windownumber;
172   PetscFunctionReturn(0);
173 }
174 
175 /*@C
176     PetscViewerDrawGetDrawLG - Returns PetscDrawLG object from PetscViewer object.
177     This PetscDrawLG object may then be used to perform graphics using
178     PetscDrawLGXXX() commands.
179 
180     Collective on PetscViewer
181 
182     Input Parameter:
183 +   PetscViewer - the PetscViewer (created with PetscViewerDrawOpen())
184 -   windownumber - indicates which subwindow (usually 0)
185 
186     Ouput Parameter:
187 .   draw - the draw line graph object
188 
189     Level: intermediate
190 
191 .seealso: PetscViewerDrawGetDraw(), PetscViewerDrawGetAxis(), PetscViewerDrawOpen()
192 @*/
193 PetscErrorCode  PetscViewerDrawGetDrawLG(PetscViewer viewer,PetscInt windownumber,PetscDrawLG *drawlg)
194 {
195   PetscErrorCode   ierr;
196   PetscBool        isdraw;
197   PetscViewer_Draw *vdraw;
198 
199   PetscFunctionBegin;
200   PetscValidHeaderSpecific(viewer,PETSC_VIEWER_CLASSID,1);
201   PetscValidLogicalCollectiveInt(viewer,windownumber,2);
202   PetscValidPointer(drawlg,3);
203   ierr = PetscObjectTypeCompare((PetscObject)viewer,PETSCVIEWERDRAW,&isdraw);CHKERRQ(ierr);
204   if (!isdraw) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_WRONG,"Must be draw type PetscViewer");
205   if (windownumber < 0) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_OUTOFRANGE,"Window number cannot be negative");
206   vdraw = (PetscViewer_Draw*)viewer->data;
207 
208   if (windownumber+vdraw->draw_base >= vdraw->draw_max || !vdraw->draw[windownumber+vdraw->draw_base]) {
209     ierr = PetscViewerDrawGetDraw(viewer,windownumber,NULL);CHKERRQ(ierr);
210   }
211   if (!vdraw->drawlg[windownumber+vdraw->draw_base]) {
212     ierr = PetscDrawLGCreate(vdraw->draw[windownumber+vdraw->draw_base],1,&vdraw->drawlg[windownumber+vdraw->draw_base]);CHKERRQ(ierr);
213     ierr = PetscLogObjectParent((PetscObject)viewer,(PetscObject)vdraw->drawlg[windownumber+vdraw->draw_base]);CHKERRQ(ierr);
214     ierr = PetscDrawLGSetFromOptions(vdraw->drawlg[windownumber+vdraw->draw_base]);CHKERRQ(ierr);
215   }
216   *drawlg = vdraw->drawlg[windownumber+vdraw->draw_base];
217   PetscFunctionReturn(0);
218 }
219 
220 /*@C
221     PetscViewerDrawGetDrawAxis - Returns PetscDrawAxis object from PetscViewer object.
222     This PetscDrawAxis object may then be used to perform graphics using
223     PetscDrawAxisXXX() commands.
224 
225     Collective on PetscViewer
226 
227     Input Parameter:
228 +   viewer - the PetscViewer (created with PetscViewerDrawOpen()
229 -   windownumber - indicates which subwindow (usually 0)
230 
231     Ouput Parameter:
232 .   drawaxis - the draw axis object
233 
234     Level: advanced
235 
236 .seealso: PetscViewerDrawGetDraw(), PetscViewerDrawGetLG(), PetscViewerDrawOpen()
237 @*/
238 PetscErrorCode  PetscViewerDrawGetDrawAxis(PetscViewer viewer,PetscInt windownumber,PetscDrawAxis *drawaxis)
239 {
240   PetscErrorCode   ierr;
241   PetscBool        isdraw;
242   PetscViewer_Draw *vdraw;
243 
244   PetscFunctionBegin;
245   PetscValidHeaderSpecific(viewer,PETSC_VIEWER_CLASSID,1);
246   PetscValidLogicalCollectiveInt(viewer,windownumber,2);
247   PetscValidPointer(drawaxis,3);
248   ierr = PetscObjectTypeCompare((PetscObject)viewer,PETSCVIEWERDRAW,&isdraw);CHKERRQ(ierr);
249   if (!isdraw) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_WRONG,"Must be draw type PetscViewer");
250   if (windownumber < 0) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_OUTOFRANGE,"Window number cannot be negative");
251   vdraw = (PetscViewer_Draw*)viewer->data;
252 
253   if (windownumber+vdraw->draw_base >= vdraw->draw_max || !vdraw->draw[windownumber+vdraw->draw_base]) {
254     ierr = PetscViewerDrawGetDraw(viewer,windownumber,NULL);CHKERRQ(ierr);
255   }
256   if (!vdraw->drawaxis[windownumber+vdraw->draw_base]) {
257     ierr = PetscDrawAxisCreate(vdraw->draw[windownumber+vdraw->draw_base],&vdraw->drawaxis[windownumber+vdraw->draw_base]);CHKERRQ(ierr);
258     ierr = PetscLogObjectParent((PetscObject)viewer,(PetscObject)vdraw->drawaxis[windownumber+vdraw->draw_base]);CHKERRQ(ierr);
259   }
260   *drawaxis = vdraw->drawaxis[windownumber+vdraw->draw_base];
261   PetscFunctionReturn(0);
262 }
263 
264 PetscErrorCode  PetscViewerDrawResize(PetscViewer v,int w,int h)
265 {
266   PetscErrorCode   ierr;
267   PetscViewer_Draw *vdraw;
268   PetscBool        isdraw;
269 
270   PetscFunctionBegin;
271   PetscValidHeaderSpecific(v,PETSC_VIEWER_CLASSID,1);
272   ierr = PetscObjectTypeCompare((PetscObject)v,PETSCVIEWERDRAW,&isdraw);CHKERRQ(ierr);
273   if (!isdraw) PetscFunctionReturn(0);
274   vdraw = (PetscViewer_Draw*)v->data;
275 
276   if (w >= 1) vdraw->w = w;
277   if (h >= 1) vdraw->h = h;
278   PetscFunctionReturn(0);
279 }
280 
281 PetscErrorCode  PetscViewerDrawSetInfo(PetscViewer v,const char display[],const char title[],int x,int y,int w,int h)
282 {
283   PetscErrorCode   ierr;
284   PetscViewer_Draw *vdraw;
285   PetscBool        isdraw;
286 
287   PetscFunctionBegin;
288   PetscValidHeaderSpecific(v,PETSC_VIEWER_CLASSID,1);
289   ierr = PetscObjectTypeCompare((PetscObject)v,PETSCVIEWERDRAW,&isdraw);CHKERRQ(ierr);
290   if (!isdraw) PetscFunctionReturn(0);
291   vdraw = (PetscViewer_Draw*)v->data;
292 
293   ierr = PetscStrallocpy(display,&vdraw->display);CHKERRQ(ierr);
294   ierr = PetscStrallocpy(title,&vdraw->title);CHKERRQ(ierr);
295   if (w >= 1) vdraw->w = w;
296   if (h >= 1) vdraw->h = h;
297   PetscFunctionReturn(0);
298 }
299 
300 PetscErrorCode  PetscViewerDrawSetDrawType(PetscViewer v,PetscDrawType drawtype)
301 {
302   PetscErrorCode   ierr;
303   PetscViewer_Draw *vdraw;
304   PetscBool        isdraw;
305 
306   PetscFunctionBegin;
307   PetscValidHeaderSpecific(v,PETSC_VIEWER_CLASSID,1);
308   ierr = PetscObjectTypeCompare((PetscObject)v,PETSCVIEWERDRAW,&isdraw);CHKERRQ(ierr);
309   if (!isdraw) PetscFunctionReturn(0);
310   vdraw = (PetscViewer_Draw*)v->data;
311 
312   ierr = PetscFree(vdraw->drawtype);CHKERRQ(ierr);
313   ierr = PetscStrallocpy(drawtype,(char**)&vdraw->drawtype);CHKERRQ(ierr);
314   PetscFunctionReturn(0);
315 }
316 
317 PetscErrorCode PetscViewerDrawGetDrawType(PetscViewer v,PetscDrawType *drawtype)
318 {
319   PetscErrorCode   ierr;
320   PetscViewer_Draw *vdraw;
321   PetscBool        isdraw;
322 
323   PetscFunctionBegin;
324   PetscValidHeaderSpecific(v,PETSC_VIEWER_CLASSID,1);
325   ierr = PetscObjectTypeCompare((PetscObject)v,PETSCVIEWERDRAW,&isdraw);CHKERRQ(ierr);
326   if (!isdraw) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_WRONG,"Must be draw type PetscViewer");
327   vdraw = (PetscViewer_Draw*)v->data;
328 
329   *drawtype = vdraw->drawtype;
330   PetscFunctionReturn(0);
331 }
332 
333 PetscErrorCode PetscViewerDrawSetTitle(PetscViewer v,const char title[])
334 {
335   PetscErrorCode   ierr;
336   PetscViewer_Draw *vdraw;
337   PetscBool        isdraw;
338 
339   PetscFunctionBegin;
340   PetscValidHeaderSpecific(v,PETSC_VIEWER_CLASSID,1);
341   ierr = PetscObjectTypeCompare((PetscObject)v,PETSCVIEWERDRAW,&isdraw);CHKERRQ(ierr);
342   if (!isdraw) PetscFunctionReturn(0);
343   vdraw = (PetscViewer_Draw*)v->data;
344 
345   ierr = PetscFree(vdraw->title);CHKERRQ(ierr);
346   ierr = PetscStrallocpy(title,&vdraw->title);CHKERRQ(ierr);
347   PetscFunctionReturn(0);
348 }
349 
350 PetscErrorCode PetscViewerDrawGetTitle(PetscViewer v,const char *title[])
351 {
352   PetscErrorCode   ierr;
353   PetscViewer_Draw *vdraw;
354   PetscBool        isdraw;
355 
356   PetscFunctionBegin;
357   PetscValidHeaderSpecific(v,PETSC_VIEWER_CLASSID,1);
358   ierr = PetscObjectTypeCompare((PetscObject)v,PETSCVIEWERDRAW,&isdraw);CHKERRQ(ierr);
359   if (!isdraw) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_WRONG,"Must be draw type PetscViewer");
360   vdraw = (PetscViewer_Draw*)v->data;
361 
362   *title = vdraw->title;
363   PetscFunctionReturn(0);
364 }
365 
366 /*@C
367    PetscViewerDrawOpen - Opens a window for use as a PetscViewer. If you want to
368    do graphics in this window, you must call PetscViewerDrawGetDraw() and
369    perform the graphics on the PetscDraw object.
370 
371    Collective
372 
373    Input Parameters:
374 +  comm - communicator that will share window
375 .  display - the X display on which to open, or null for the local machine
376 .  title - the title to put in the title bar, or null for no title
377 .  x, y - the screen coordinates of the upper left corner of window, or use PETSC_DECIDE
378 -  w, h - window width and height in pixels, or may use PETSC_DECIDE or PETSC_DRAW_FULL_SIZE, PETSC_DRAW_HALF_SIZE,
379           PETSC_DRAW_THIRD_SIZE, PETSC_DRAW_QUARTER_SIZE
380 
381    Output Parameters:
382 . viewer - the PetscViewer
383 
384    Format Options:
385 +  PETSC_VIEWER_DRAW_BASIC - displays with basic format
386 -  PETSC_VIEWER_DRAW_LG    - displays using a line graph
387 
388    Options Database Keys:
389    PetscViewerDrawOpen() calls PetscDrawCreate(), so see the manual page for
390    PetscDrawCreate() for runtime options, including
391 +  -draw_type x or null
392 .  -nox - Disables all x-windows output
393 .  -display <name> - Specifies name of machine for the X display
394 .  -geometry <x,y,w,h> - allows setting the window location and size
395 -  -draw_pause <pause> - Sets time (in seconds) that the
396      program pauses after PetscDrawPause() has been called
397      (0 is default, -1 implies until user input).
398 
399    Level: beginner
400 
401    Note for Fortran Programmers:
402    Whenever indicating null character data in a Fortran code,
403    PETSC_NULL_CHARACTER must be employed; using NULL is not
404    correct for character data!  Thus, PETSC_NULL_CHARACTER can be
405    used for the display and title input parameters.
406 
407 
408 
409 .seealso: PetscDrawCreate(), PetscViewerDestroy(), PetscViewerDrawGetDraw(), PetscViewerCreate(), PETSC_VIEWER_DRAW_,
410           PETSC_VIEWER_DRAW_WORLD, PETSC_VIEWER_DRAW_SELF
411 @*/
412 PetscErrorCode  PetscViewerDrawOpen(MPI_Comm comm,const char display[],const char title[],int x,int y,int w,int h,PetscViewer *viewer)
413 {
414   PetscErrorCode ierr;
415 
416   PetscFunctionBegin;
417   ierr = PetscViewerCreate(comm,viewer);CHKERRQ(ierr);
418   ierr = PetscViewerSetType(*viewer,PETSCVIEWERDRAW);CHKERRQ(ierr);
419   ierr = PetscViewerDrawSetInfo(*viewer,display,title,x,y,w,h);CHKERRQ(ierr);
420   PetscFunctionReturn(0);
421 }
422 
423 PetscErrorCode PetscViewerGetSubViewer_Draw(PetscViewer viewer,MPI_Comm comm,PetscViewer *sviewer)
424 {
425   PetscErrorCode   ierr;
426   PetscMPIInt      rank;
427   PetscInt         i;
428   PetscViewer_Draw *vdraw = (PetscViewer_Draw*)viewer->data,*svdraw;
429 
430   PetscFunctionBegin;
431   if (vdraw->singleton_made) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ORDER,"Trying to get SubViewer without first restoring previous");
432   /* only processor zero can use the PetscViewer draw singleton */
433   if (sviewer) *sviewer = NULL;
434   ierr = MPI_Comm_rank(PetscObjectComm((PetscObject)viewer),&rank);CHKERRQ(ierr);
435   if (!rank) {
436     PetscMPIInt flg;
437 
438     ierr = MPI_Comm_compare(PETSC_COMM_SELF,comm,&flg);CHKERRQ(ierr);
439     if (flg != MPI_IDENT && flg != MPI_CONGRUENT) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_SUP,"PetscViewerGetSubViewer() for PETSCVIEWERDRAW requires a singleton MPI_Comm");
440     ierr = PetscViewerCreate(comm,sviewer);CHKERRQ(ierr);
441     ierr = PetscViewerSetType(*sviewer,PETSCVIEWERDRAW);CHKERRQ(ierr);
442     svdraw = (PetscViewer_Draw*)(*sviewer)->data;
443     (*sviewer)->format = viewer->format;
444     for (i=0; i<vdraw->draw_max; i++) { /* XXX this is wrong if svdraw->draw_max (initially 5) < vdraw->draw_max */
445       if (vdraw->draw[i]) {ierr = PetscDrawGetSingleton(vdraw->draw[i],&svdraw->draw[i]);CHKERRQ(ierr);}
446     }
447   }
448   vdraw->singleton_made = PETSC_TRUE;
449   PetscFunctionReturn(0);
450 }
451 
452 PetscErrorCode PetscViewerRestoreSubViewer_Draw(PetscViewer viewer,MPI_Comm comm,PetscViewer *sviewer)
453 {
454   PetscErrorCode   ierr;
455   PetscMPIInt      rank;
456   PetscInt         i;
457   PetscViewer_Draw *vdraw = (PetscViewer_Draw*)viewer->data,*svdraw;
458 
459   PetscFunctionBegin;
460   if (!vdraw->singleton_made) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ORDER,"Trying to restore a singleton that was not gotten");
461   ierr = MPI_Comm_rank(PetscObjectComm((PetscObject)viewer),&rank);CHKERRQ(ierr);
462   if (!rank) {
463     svdraw = (PetscViewer_Draw*)(*sviewer)->data;
464     for (i=0; i<vdraw->draw_max; i++) {
465       if (vdraw->draw[i] && svdraw->draw[i]) {
466         ierr = PetscDrawRestoreSingleton(vdraw->draw[i],&svdraw->draw[i]);CHKERRQ(ierr);
467       }
468     }
469     ierr = PetscFree3(svdraw->draw,svdraw->drawlg,svdraw->drawaxis);CHKERRQ(ierr);
470     ierr = PetscFree((*sviewer)->data);CHKERRQ(ierr);
471     ierr = PetscHeaderDestroy(sviewer);CHKERRQ(ierr);
472   }
473   vdraw->singleton_made = PETSC_FALSE;
474   PetscFunctionReturn(0);
475 }
476 
477 PetscErrorCode PetscViewerSetFromOptions_Draw(PetscOptionItems *PetscOptionsObject,PetscViewer v)
478 {
479   PetscErrorCode ierr;
480   PetscReal      bounds[16];
481   PetscInt       nbounds = 16;
482   PetscBool      flg;
483 
484   PetscFunctionBegin;
485   ierr = PetscOptionsHead(PetscOptionsObject,"Draw PetscViewer Options");CHKERRQ(ierr);
486   ierr = PetscOptionsRealArray("-draw_bounds","Bounds to put on plots axis","PetscViewerDrawSetBounds",bounds,&nbounds,&flg);CHKERRQ(ierr);
487   if (flg) {
488     ierr = PetscViewerDrawSetBounds(v,nbounds/2,bounds);CHKERRQ(ierr);
489   }
490   ierr = PetscOptionsTail();CHKERRQ(ierr);
491   PetscFunctionReturn(0);
492 }
493 
494 PetscErrorCode PetscViewerView_Draw(PetscViewer viewer,PetscViewer v)
495 {
496   PetscErrorCode   ierr;
497   PetscDraw        draw;
498   PetscInt         i;
499   PetscViewer_Draw *vdraw = (PetscViewer_Draw*)viewer->data;
500 
501   PetscFunctionBegin;
502   /*  If the PetscViewer has just been created then no vdraw->draw yet
503       exists so this will not actually call the viewer on any draws. */
504   for (i=0; i<vdraw->draw_base; i++) {
505     if (vdraw->draw[i]) {
506       ierr = PetscViewerDrawGetDraw(viewer,i,&draw);CHKERRQ(ierr);
507       ierr = PetscDrawView(draw,v);CHKERRQ(ierr);
508     }
509   }
510   PetscFunctionReturn(0);
511 }
512 
513 /*MC
514    PETSCVIEWERDRAW - A viewer that generates graphics, either to the screen or a file
515 
516 
517 .seealso:  PetscViewerDrawOpen(), PetscViewerDrawGetDraw(), PETSC_VIEWER_DRAW_(),PETSC_VIEWER_DRAW_SELF, PETSC_VIEWER_DRAW_WORLD,
518            PetscViewerCreate(), PetscViewerASCIIOpen(), PetscViewerBinaryOpen(), PETSCVIEWERBINARY,
519            PetscViewerMatlabOpen(), VecView(), DMView(), PetscViewerMatlabPutArray(), PETSCVIEWERASCII, PETSCVIEWERMATLAB,
520            PetscViewerFileSetName(), PetscViewerFileSetMode(), PetscViewerFormat, PetscViewerType, PetscViewerSetType()
521 
522   Level: beginner
523 
524 M*/
525 PETSC_EXTERN PetscErrorCode PetscViewerCreate_Draw(PetscViewer viewer)
526 {
527   PetscErrorCode   ierr;
528   PetscViewer_Draw *vdraw;
529 
530   PetscFunctionBegin;
531   ierr = PetscNewLog(viewer,&vdraw);CHKERRQ(ierr);
532   viewer->data = (void*)vdraw;
533 
534   viewer->ops->flush            = PetscViewerFlush_Draw;
535   viewer->ops->view             = PetscViewerView_Draw;
536   viewer->ops->destroy          = PetscViewerDestroy_Draw;
537   viewer->ops->setfromoptions   = PetscViewerSetFromOptions_Draw;
538   viewer->ops->getsubviewer     = PetscViewerGetSubViewer_Draw;
539   viewer->ops->restoresubviewer = PetscViewerRestoreSubViewer_Draw;
540 
541   /* these are created on the fly if requested */
542   vdraw->draw_max  = 5;
543   vdraw->draw_base = 0;
544   vdraw->w         = PETSC_DECIDE;
545   vdraw->h         = PETSC_DECIDE;
546 
547   ierr = PetscCalloc3(vdraw->draw_max,&vdraw->draw,vdraw->draw_max,&vdraw->drawlg,vdraw->draw_max,&vdraw->drawaxis);CHKERRQ(ierr);
548   vdraw->singleton_made = PETSC_FALSE;
549   PetscFunctionReturn(0);
550 }
551 
552 /*@
553     PetscViewerDrawClear - Clears a PetscDraw graphic associated with a PetscViewer.
554 
555     Not Collective
556 
557     Input Parameter:
558 .  viewer - the PetscViewer
559 
560     Level: intermediate
561 
562 .seealso: PetscViewerDrawOpen(), PetscViewerDrawGetDraw(),
563 
564 @*/
565 PetscErrorCode  PetscViewerDrawClear(PetscViewer viewer)
566 {
567   PetscErrorCode   ierr;
568   PetscViewer_Draw *vdraw;
569   PetscBool        isdraw;
570   PetscInt         i;
571 
572   PetscFunctionBegin;
573   PetscValidHeaderSpecific(viewer,PETSC_VIEWER_CLASSID,1);
574   ierr = PetscObjectTypeCompare((PetscObject)viewer,PETSCVIEWERDRAW,&isdraw);CHKERRQ(ierr);
575   if (!isdraw) PetscFunctionReturn(0);
576   vdraw = (PetscViewer_Draw*)viewer->data;
577 
578   for (i=0; i<vdraw->draw_max; i++) {
579     if (vdraw->draw[i]) {ierr = PetscDrawClear(vdraw->draw[i]);CHKERRQ(ierr);}
580   }
581   PetscFunctionReturn(0);
582 }
583 
584 /*@
585     PetscViewerDrawGetPause - Gets a pause for the first present draw
586 
587     Not Collective
588 
589     Input Parameter:
590 .  viewer - the PetscViewer
591 
592     Output Parameter:
593 .  pause - the pause value
594 
595     Level: intermediate
596 
597 .seealso: PetscViewerDrawOpen(), PetscViewerDrawGetDraw(),
598 
599 @*/
600 PetscErrorCode  PetscViewerDrawGetPause(PetscViewer viewer,PetscReal *pause)
601 {
602   PetscErrorCode   ierr;
603   PetscViewer_Draw *vdraw;
604   PetscBool        isdraw;
605   PetscInt         i;
606   PetscDraw        draw;
607 
608   PetscFunctionBegin;
609   PetscValidHeaderSpecific(viewer,PETSC_VIEWER_CLASSID,1);
610   ierr = PetscObjectTypeCompare((PetscObject)viewer,PETSCVIEWERDRAW,&isdraw);CHKERRQ(ierr);
611   if (!isdraw) {*pause = 0.0; PetscFunctionReturn(0);}
612   vdraw = (PetscViewer_Draw*)viewer->data;
613 
614   for (i=0; i<vdraw->draw_max; i++) {
615     if (vdraw->draw[i]) {
616       ierr = PetscDrawGetPause(vdraw->draw[i],pause);CHKERRQ(ierr);
617       PetscFunctionReturn(0);
618     }
619   }
620   /* none exist yet so create one and get its pause */
621   ierr = PetscViewerDrawGetDraw(viewer,0,&draw);CHKERRQ(ierr);
622   ierr = PetscDrawGetPause(draw,pause);CHKERRQ(ierr);
623   PetscFunctionReturn(0);
624 }
625 
626 /*@
627     PetscViewerDrawSetPause - Sets a pause for each PetscDraw in the viewer
628 
629     Not Collective
630 
631     Input Parameters:
632 +  viewer - the PetscViewer
633 -  pause - the pause value
634 
635     Level: intermediate
636 
637 .seealso: PetscViewerDrawOpen(), PetscViewerDrawGetDraw(),
638 
639 @*/
640 PetscErrorCode  PetscViewerDrawSetPause(PetscViewer viewer,PetscReal pause)
641 {
642   PetscErrorCode   ierr;
643   PetscViewer_Draw *vdraw;
644   PetscBool        isdraw;
645   PetscInt         i;
646 
647   PetscFunctionBegin;
648   PetscValidHeaderSpecific(viewer,PETSC_VIEWER_CLASSID,1);
649   ierr = PetscObjectTypeCompare((PetscObject)viewer,PETSCVIEWERDRAW,&isdraw);CHKERRQ(ierr);
650   if (!isdraw) PetscFunctionReturn(0);
651   vdraw = (PetscViewer_Draw*)viewer->data;
652 
653   vdraw->pause = pause;
654   for (i=0; i<vdraw->draw_max; i++) {
655     if (vdraw->draw[i]) {ierr = PetscDrawSetPause(vdraw->draw[i],pause);CHKERRQ(ierr);}
656   }
657   PetscFunctionReturn(0);
658 }
659 
660 
661 /*@
662     PetscViewerDrawSetHold - Holds previous image when drawing new image
663 
664     Not Collective
665 
666     Input Parameters:
667 +  viewer - the PetscViewer
668 -  hold - indicates to hold or not
669 
670     Level: intermediate
671 
672 .seealso: PetscViewerDrawOpen(), PetscViewerDrawGetDraw(),
673 
674 @*/
675 PetscErrorCode  PetscViewerDrawSetHold(PetscViewer viewer,PetscBool hold)
676 {
677   PetscErrorCode   ierr;
678   PetscViewer_Draw *vdraw;
679   PetscBool        isdraw;
680 
681   PetscFunctionBegin;
682   PetscValidHeaderSpecific(viewer,PETSC_VIEWER_CLASSID,1);
683   ierr = PetscObjectTypeCompare((PetscObject)viewer,PETSCVIEWERDRAW,&isdraw);CHKERRQ(ierr);
684   if (!isdraw) PetscFunctionReturn(0);
685   vdraw = (PetscViewer_Draw*)viewer->data;
686 
687   vdraw->hold = hold;
688   PetscFunctionReturn(0);
689 }
690 
691 /*@
692     PetscViewerDrawGetHold - Checks if holds previous image when drawing new image
693 
694     Not Collective
695 
696     Input Parameter:
697 .  viewer - the PetscViewer
698 
699     Output Parameter:
700 .  hold - indicates to hold or not
701 
702     Level: intermediate
703 
704 .seealso: PetscViewerDrawOpen(), PetscViewerDrawGetDraw(),
705 
706 @*/
707 PetscErrorCode  PetscViewerDrawGetHold(PetscViewer viewer,PetscBool *hold)
708 {
709   PetscErrorCode   ierr;
710   PetscViewer_Draw *vdraw;
711   PetscBool        isdraw;
712 
713   PetscFunctionBegin;
714   PetscValidHeaderSpecific(viewer,PETSC_VIEWER_CLASSID,1);
715   ierr = PetscObjectTypeCompare((PetscObject)viewer,PETSCVIEWERDRAW,&isdraw);CHKERRQ(ierr);
716   if (!isdraw) {*hold = PETSC_FALSE; PetscFunctionReturn(0);}
717   vdraw = (PetscViewer_Draw*)viewer->data;
718 
719   *hold = vdraw->hold;
720   PetscFunctionReturn(0);
721 }
722 
723 /* ---------------------------------------------------------------------*/
724 /*
725     The variable Petsc_Viewer_Draw_keyval is used to indicate an MPI attribute that
726   is attached to a communicator, in this case the attribute is a PetscViewer.
727 */
728 PetscMPIInt Petsc_Viewer_Draw_keyval = MPI_KEYVAL_INVALID;
729 
730 /*@C
731     PETSC_VIEWER_DRAW_ - Creates a window PetscViewer shared by all processors
732                      in a communicator.
733 
734      Collective
735 
736      Input Parameter:
737 .    comm - the MPI communicator to share the window PetscViewer
738 
739      Level: intermediate
740 
741      Notes:
742      Unlike almost all other PETSc routines, PETSC_VIEWER_DRAW_ does not return
743      an error code.  The window is usually used in the form
744 $       XXXView(XXX object,PETSC_VIEWER_DRAW_(comm));
745 
746 .seealso: PETSC_VIEWER_DRAW_WORLD, PETSC_VIEWER_DRAW_SELF, PetscViewerDrawOpen(),
747 @*/
748 PetscViewer  PETSC_VIEWER_DRAW_(MPI_Comm comm)
749 {
750   PetscErrorCode ierr;
751   PetscMPIInt    flag;
752   PetscViewer    viewer;
753   MPI_Comm       ncomm;
754 
755   PetscFunctionBegin;
756   ierr = PetscCommDuplicate(comm,&ncomm,NULL);if (ierr) {PetscError(PETSC_COMM_SELF,__LINE__,"PETSC_VIEWER_DRAW_",__FILE__,PETSC_ERR_PLIB,PETSC_ERROR_INITIAL," ");PetscFunctionReturn(NULL);}
757   if (Petsc_Viewer_Draw_keyval == MPI_KEYVAL_INVALID) {
758     ierr = MPI_Comm_create_keyval(MPI_COMM_NULL_COPY_FN,MPI_COMM_NULL_DELETE_FN,&Petsc_Viewer_Draw_keyval,NULL);
759     if (ierr) {PetscError(PETSC_COMM_SELF,__LINE__,"PETSC_VIEWER_DRAW_",__FILE__,PETSC_ERR_PLIB,PETSC_ERROR_INITIAL," ");PetscFunctionReturn(NULL);}
760   }
761   ierr = MPI_Comm_get_attr(ncomm,Petsc_Viewer_Draw_keyval,(void**)&viewer,&flag);
762   if (ierr) {PetscError(PETSC_COMM_SELF,__LINE__,"PETSC_VIEWER_DRAW_",__FILE__,PETSC_ERR_PLIB,PETSC_ERROR_INITIAL," ");PetscFunctionReturn(NULL);}
763   if (!flag) { /* PetscViewer not yet created */
764     ierr = PetscViewerDrawOpen(ncomm,NULL,NULL,PETSC_DECIDE,PETSC_DECIDE,300,300,&viewer);
765     if (ierr) {PetscError(PETSC_COMM_SELF,__LINE__,"PETSC_VIEWER_DRAW_",__FILE__,PETSC_ERR_PLIB,PETSC_ERROR_INITIAL," ");PetscFunctionReturn(NULL);}
766     ierr = PetscObjectRegisterDestroy((PetscObject)viewer);
767     if (ierr) {PetscError(PETSC_COMM_SELF,__LINE__,"PETSC_VIEWER_DRAW_",__FILE__,PETSC_ERR_PLIB,PETSC_ERROR_INITIAL," ");PetscFunctionReturn(NULL);}
768     ierr = MPI_Comm_set_attr(ncomm,Petsc_Viewer_Draw_keyval,(void*)viewer);
769     if (ierr) {PetscError(PETSC_COMM_SELF,__LINE__,"PETSC_VIEWER_DRAW_",__FILE__,PETSC_ERR_PLIB,PETSC_ERROR_INITIAL," ");PetscFunctionReturn(NULL);}
770   }
771   ierr = PetscCommDestroy(&ncomm);
772   if (ierr) {PetscError(PETSC_COMM_SELF,__LINE__,"PETSC_VIEWER_DRAW_",__FILE__,PETSC_ERR_PLIB,PETSC_ERROR_INITIAL," ");PetscFunctionReturn(NULL);}
773   PetscFunctionReturn(viewer);
774 }
775 
776 /*@
777     PetscViewerDrawSetBounds - sets the upper and lower bounds to be used in plotting
778 
779     Collective on PetscViewer
780 
781     Input Parameters:
782 +   viewer - the PetscViewer (created with PetscViewerDrawOpen())
783 .   nbounds - number of plots that can be made with this viewer, for example the dof passed to DMDACreate()
784 -   bounds - the actual bounds, the size of this is 2*nbounds, the values are stored in the order min F_0, max F_0, min F_1, max F_1, .....
785 
786 
787     Options Database:
788 .   -draw_bounds  minF0,maxF0,minF1,maxF1
789 
790     Level: intermediate
791 
792     Notes:
793     this determines the colors used in 2d contour plots generated with VecView() for DMDA in 2d. Any values in the vector below or above the
794       bounds are moved to the bound value before plotting. In this way the color index from color to physical value remains the same for all plots generated with
795       this viewer. Otherwise the color to physical value meaning changes with each new image if this is not set.
796 
797 
798 .seealso: PetscViewerDrawGetLG(), PetscViewerDrawGetAxis(), PetscViewerDrawOpen()
799 @*/
800 PetscErrorCode  PetscViewerDrawSetBounds(PetscViewer viewer,PetscInt nbounds,const PetscReal *bounds)
801 {
802   PetscViewer_Draw *vdraw;
803   PetscBool        isdraw;
804   PetscErrorCode   ierr;
805 
806 
807   PetscFunctionBegin;
808   PetscValidHeaderSpecific(viewer,PETSC_VIEWER_CLASSID,1);
809   ierr = PetscObjectTypeCompare((PetscObject)viewer,PETSCVIEWERDRAW,&isdraw);CHKERRQ(ierr);
810   if (!isdraw) PetscFunctionReturn(0);
811   vdraw = (PetscViewer_Draw*)viewer->data;
812 
813   vdraw->nbounds = nbounds;
814   ierr = PetscFree(vdraw->bounds);CHKERRQ(ierr);
815   ierr = PetscMalloc1(2*nbounds,&vdraw->bounds);CHKERRQ(ierr);
816   ierr = PetscArraycpy(vdraw->bounds,bounds,2*nbounds);CHKERRQ(ierr);
817   PetscFunctionReturn(0);
818 }
819 
820 /*@C
821     PetscViewerDrawGetBounds - gets the upper and lower bounds to be used in plotting set with PetscViewerDrawSetBounds()
822 
823     Collective on PetscViewer
824 
825     Input Parameter:
826 .   viewer - the PetscViewer (created with PetscViewerDrawOpen())
827 
828     Output Parameters:
829 +   nbounds - number of plots that can be made with this viewer, for example the dof passed to DMDACreate()
830 -   bounds - the actual bounds, the size of this is 2*nbounds, the values are stored in the order min F_0, max F_0, min F_1, max F_1, .....
831 
832     Level: intermediate
833 
834 
835 .seealso: PetscViewerDrawGetLG(), PetscViewerDrawGetAxis(), PetscViewerDrawOpen(), PetscViewerDrawSetBounds()
836 @*/
837 PetscErrorCode  PetscViewerDrawGetBounds(PetscViewer viewer,PetscInt *nbounds,const PetscReal **bounds)
838 {
839   PetscViewer_Draw *vdraw;
840   PetscBool        isdraw;
841   PetscErrorCode   ierr;
842 
843   PetscFunctionBegin;
844   PetscValidHeaderSpecific(viewer,PETSC_VIEWER_CLASSID,1);
845   ierr = PetscObjectTypeCompare((PetscObject)viewer,PETSCVIEWERDRAW,&isdraw);CHKERRQ(ierr);
846   if (!isdraw) {if (nbounds) *nbounds = 0; if (bounds) *bounds = NULL; PetscFunctionReturn(0);}
847   vdraw = (PetscViewer_Draw*)viewer->data;
848 
849   if (nbounds) *nbounds = vdraw->nbounds;
850   if (bounds)  *bounds  = vdraw->bounds;
851   PetscFunctionReturn(0);
852 }
853