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