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