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