xref: /petsc/src/sys/classes/viewer/impls/draw/drawv.c (revision 009bbdc485cd9ad46be9940d3549e2dde9cdc322)
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   vdraw->w         = PETSC_DECIDE;
440   vdraw->h         = PETSC_DECIDE;
441   ierr = PetscMalloc3(vdraw->draw_max,PetscDraw,&vdraw->draw,vdraw->draw_max,PetscDrawLG,&vdraw->drawlg,vdraw->draw_max,PetscDrawAxis,&vdraw->drawaxis);CHKERRQ(ierr);
442   ierr = PetscMemzero(vdraw->draw,vdraw->draw_max*sizeof(PetscDraw));CHKERRQ(ierr);
443   ierr = PetscMemzero(vdraw->drawlg,vdraw->draw_max*sizeof(PetscDrawLG));CHKERRQ(ierr);
444   ierr = PetscMemzero(vdraw->drawaxis,vdraw->draw_max*sizeof(PetscDrawAxis));CHKERRQ(ierr);
445   for (i=0; i<vdraw->draw_max; i++) {
446     vdraw->draw[i]     = 0;
447     vdraw->drawlg[i]   = 0;
448     vdraw->drawaxis[i] = 0;
449   }
450   vdraw->singleton_made = PETSC_FALSE;
451   PetscFunctionReturn(0);
452 }
453 EXTERN_C_END
454 
455 #undef __FUNCT__
456 #define __FUNCT__ "PetscViewerDrawClear"
457 /*@
458     PetscViewerDrawClear - Clears a PetscDraw graphic associated with a PetscViewer.
459 
460     Not Collective
461 
462     Input Parameter:
463 .  viewer - the PetscViewer
464 
465     Level: intermediate
466 
467 .seealso: PetscViewerDrawOpen(), PetscViewerDrawGetDraw(),
468 
469 @*/
470 PetscErrorCode  PetscViewerDrawClear(PetscViewer viewer)
471 {
472   PetscErrorCode   ierr;
473   PetscInt         i;
474   PetscBool        isdraw;
475   PetscViewer_Draw *vdraw;
476 
477   PetscFunctionBegin;
478   ierr = PetscObjectTypeCompare((PetscObject)viewer,PETSCVIEWERDRAW,&isdraw);CHKERRQ(ierr);
479   if (isdraw) {
480     vdraw = (PetscViewer_Draw*)viewer->data;
481     for (i=0; i<vdraw->draw_max; i++) {
482       if (vdraw->draw[i]) {ierr = PetscDrawClear(vdraw->draw[i]);CHKERRQ(ierr);}
483     }
484   }
485   PetscFunctionReturn(0);
486 }
487 
488 #undef __FUNCT__
489 #define __FUNCT__ "PetscViewerDrawGetPause"
490 /*@
491     PetscViewerDrawGetPause - Gets a pause for the first present draw
492 
493     Not Collective
494 
495     Input Parameter:
496 .  viewer - the PetscViewer
497 
498     Output Parameter:
499 .  pause - the pause value
500 
501     Level: intermediate
502 
503 .seealso: PetscViewerDrawOpen(), PetscViewerDrawGetDraw(),
504 
505 @*/
506 PetscErrorCode  PetscViewerDrawGetPause(PetscViewer viewer,PetscReal *pause)
507 {
508   PetscErrorCode   ierr;
509   PetscInt         i;
510   PetscBool        isdraw;
511   PetscViewer_Draw *vdraw;
512   PetscDraw        draw;
513 
514   PetscFunctionBegin;
515   ierr = PetscObjectTypeCompare((PetscObject)viewer,PETSCVIEWERDRAW,&isdraw);CHKERRQ(ierr);
516   *pause = 0.0;
517   if (isdraw) {
518     vdraw = (PetscViewer_Draw*)viewer->data;
519     for (i=0; i<vdraw->draw_max; i++) {
520       if (vdraw->draw[i]) {
521         ierr = PetscDrawGetPause(vdraw->draw[i],pause);CHKERRQ(ierr);
522         PetscFunctionReturn(0);
523       }
524     }
525     /* none exist yet so create one and get its pause */
526     ierr = PetscViewerDrawGetDraw(viewer,0,&draw);CHKERRQ(ierr);
527     ierr = PetscDrawGetPause(vdraw->draw[0],pause);CHKERRQ(ierr);
528   }
529   PetscFunctionReturn(0);
530 }
531 
532 #undef __FUNCT__
533 #define __FUNCT__ "PetscViewerDrawSetPause"
534 /*@
535     PetscViewerDrawSetPause - Sets a pause for each PetscDraw in the viewer
536 
537     Not Collective
538 
539     Input Parameters:
540 +  viewer - the PetscViewer
541 -  pause - the pause value
542 
543     Level: intermediate
544 
545 .seealso: PetscViewerDrawOpen(), PetscViewerDrawGetDraw(),
546 
547 @*/
548 PetscErrorCode  PetscViewerDrawSetPause(PetscViewer viewer,PetscReal pause)
549 {
550   PetscErrorCode   ierr;
551   PetscInt         i;
552   PetscBool        isdraw;
553   PetscViewer_Draw *vdraw;
554 
555   PetscFunctionBegin;
556   ierr = PetscObjectTypeCompare((PetscObject)viewer,PETSCVIEWERDRAW,&isdraw);CHKERRQ(ierr);
557   if (isdraw) {
558     vdraw = (PetscViewer_Draw*)viewer->data;
559     for (i=0; i<vdraw->draw_max; i++) {
560       if (vdraw->draw[i]) {ierr = PetscDrawSetPause(vdraw->draw[i],pause);CHKERRQ(ierr);}
561     }
562   }
563   PetscFunctionReturn(0);
564 }
565 
566 
567 #undef __FUNCT__
568 #define __FUNCT__ "PetscViewerDrawSetHold"
569 /*@
570     PetscViewerDrawSetHold - Holds previous image when drawing new image
571 
572     Not Collective
573 
574     Input Parameters:
575 +  viewer - the PetscViewer
576 -  hold - indicates to hold or not
577 
578     Level: intermediate
579 
580 .seealso: PetscViewerDrawOpen(), PetscViewerDrawGetDraw(),
581 
582 @*/
583 PetscErrorCode  PetscViewerDrawSetHold(PetscViewer viewer,PetscBool hold)
584 {
585   PetscErrorCode   ierr;
586   PetscViewer_Draw *vdraw;
587   PetscBool        isdraw;
588 
589   PetscFunctionBegin;
590   ierr = PetscObjectTypeCompare((PetscObject)viewer,PETSCVIEWERDRAW,&isdraw);CHKERRQ(ierr);
591   if (isdraw) {
592     vdraw = (PetscViewer_Draw*)viewer->data;
593     vdraw->hold = hold;
594   }
595   PetscFunctionReturn(0);
596 }
597 
598 #undef __FUNCT__
599 #define __FUNCT__ "PetscViewerDrawGetHold"
600 /*@
601     PetscViewerDrawGetHold - Holds previous image when drawing new image
602 
603     Not Collective
604 
605     Input Parameter:
606 .  viewer - the PetscViewer
607 
608     Output Parameter:
609 .  hold - indicates to hold or not
610 
611     Level: intermediate
612 
613 .seealso: PetscViewerDrawOpen(), PetscViewerDrawGetDraw(),
614 
615 @*/
616 PetscErrorCode  PetscViewerDrawGetHold(PetscViewer viewer,PetscBool *hold)
617 {
618   PetscErrorCode   ierr;
619   PetscViewer_Draw *vdraw;
620   PetscBool        isdraw;
621 
622   PetscFunctionBegin;
623   ierr = PetscObjectTypeCompare((PetscObject)viewer,PETSCVIEWERDRAW,&isdraw);CHKERRQ(ierr);
624   if (isdraw) {
625     vdraw = (PetscViewer_Draw*)viewer->data;
626     *hold = vdraw->hold;
627   }
628   PetscFunctionReturn(0);
629 }
630 
631 /* ---------------------------------------------------------------------*/
632 /*
633     The variable Petsc_Viewer_Draw_keyval is used to indicate an MPI attribute that
634   is attached to a communicator, in this case the attribute is a PetscViewer.
635 */
636 static PetscMPIInt Petsc_Viewer_Draw_keyval = MPI_KEYVAL_INVALID;
637 
638 #undef __FUNCT__
639 #define __FUNCT__ "PETSC_VIEWER_DRAW_"
640 /*@C
641     PETSC_VIEWER_DRAW_ - Creates a window PetscViewer shared by all processors
642                      in a communicator.
643 
644      Collective on MPI_Comm
645 
646      Input Parameter:
647 .    comm - the MPI communicator to share the window PetscViewer
648 
649      Level: intermediate
650 
651      Notes:
652      Unlike almost all other PETSc routines, PETSC_VIEWER_DRAW_ does not return
653      an error code.  The window is usually used in the form
654 $       XXXView(XXX object,PETSC_VIEWER_DRAW_(comm));
655 
656 .seealso: PETSC_VIEWER_DRAW_WORLD, PETSC_VIEWER_DRAW_SELF, PetscViewerDrawOpen(),
657 @*/
658 PetscViewer  PETSC_VIEWER_DRAW_(MPI_Comm comm)
659 {
660   PetscErrorCode ierr;
661   PetscMPIInt    flag;
662   PetscViewer    viewer;
663   MPI_Comm       ncomm;
664 
665   PetscFunctionBegin;
666   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);}
667   if (Petsc_Viewer_Draw_keyval == MPI_KEYVAL_INVALID) {
668     ierr = MPI_Keyval_create(MPI_NULL_COPY_FN,MPI_NULL_DELETE_FN,&Petsc_Viewer_Draw_keyval,0);
669     if (ierr) {PetscError(PETSC_COMM_SELF,__LINE__,"PETSC_VIEWER_DRAW_",__FILE__,__SDIR__,PETSC_ERR_PLIB,PETSC_ERROR_INITIAL," ");PetscFunctionReturn(0);}
670   }
671   ierr = MPI_Attr_get(ncomm,Petsc_Viewer_Draw_keyval,(void **)&viewer,&flag);
672   if (ierr) {PetscError(PETSC_COMM_SELF,__LINE__,"PETSC_VIEWER_DRAW_",__FILE__,__SDIR__,PETSC_ERR_PLIB,PETSC_ERROR_INITIAL," ");PetscFunctionReturn(0);}
673   if (!flag) { /* PetscViewer not yet created */
674     ierr = PetscViewerDrawOpen(ncomm,0,0,PETSC_DECIDE,PETSC_DECIDE,300,300,&viewer);
675     if (ierr) {PetscError(PETSC_COMM_SELF,__LINE__,"PETSC_VIEWER_DRAW_",__FILE__,__SDIR__,PETSC_ERR_PLIB,PETSC_ERROR_INITIAL," ");PetscFunctionReturn(0);}
676     ierr = PetscObjectRegisterDestroy((PetscObject)viewer);
677     if (ierr) {PetscError(PETSC_COMM_SELF,__LINE__,"PETSC_VIEWER_DRAW_",__FILE__,__SDIR__,PETSC_ERR_PLIB,PETSC_ERROR_INITIAL," ");PetscFunctionReturn(0);}
678     ierr = MPI_Attr_put(ncomm,Petsc_Viewer_Draw_keyval,(void*)viewer);
679     if (ierr) {PetscError(PETSC_COMM_SELF,__LINE__,"PETSC_VIEWER_DRAW_",__FILE__,__SDIR__,PETSC_ERR_PLIB,PETSC_ERROR_INITIAL," ");PetscFunctionReturn(0);}
680   }
681   ierr = PetscCommDestroy(&ncomm);
682   if (ierr) {PetscError(PETSC_COMM_SELF,__LINE__,"PETSC_VIEWER_DRAW_",__FILE__,__SDIR__,PETSC_ERR_PLIB,PETSC_ERROR_INITIAL," ");PetscFunctionReturn(0);}
683   PetscFunctionReturn(viewer);
684 }
685 
686 #undef __FUNCT__
687 #define __FUNCT__ "PetscViewerDrawSetBounds"
688 /*@
689     PetscViewerDrawSetBounds - sets the upper and lower bounds to be used in plotting
690 
691     Collective on PetscViewer
692 
693     Input Parameters:
694 +   viewer - the PetscViewer (created with PetscViewerDrawOpen())
695 .   nbounds - number of plots that can be made with this viewer, for example the dof passed to DMDACreate()
696 -   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, .....
697 
698     Level: intermediate
699 
700     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
701       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
702       this viewer. Otherwise the color to physical value meaning changes with each new image if this is not set.
703 
704    Concepts: drawing^accessing PetscDraw context from PetscViewer
705    Concepts: graphics
706 
707 .seealso: PetscViewerDrawGetLG(), PetscViewerDrawGetAxis(), PetscViewerDrawOpen()
708 @*/
709 PetscErrorCode  PetscViewerDrawSetBounds(PetscViewer viewer,PetscInt nbounds,const PetscReal *bounds)
710 {
711   PetscViewer_Draw *vdraw = (PetscViewer_Draw*)viewer->data;
712   PetscErrorCode   ierr;
713 
714 
715   PetscFunctionBegin;
716   PetscValidHeaderSpecific(viewer,PETSC_VIEWER_CLASSID,1);
717   vdraw->nbounds   = nbounds;
718   ierr = PetscMalloc(2*nbounds*sizeof(PetscReal),&vdraw->bounds);CHKERRQ(ierr);
719   ierr = PetscMemcpy(vdraw->bounds,bounds,2*nbounds*sizeof(PetscReal));CHKERRQ(ierr);
720   PetscFunctionReturn(0);
721 }
722 
723 #undef __FUNCT__
724 #define __FUNCT__ "PetscViewerDrawGetBounds"
725 /*@C
726     PetscViewerDrawGetBounds - gets the upper and lower bounds to be used in plotting set with PetscViewerDrawSetBounds()
727 
728     Collective on PetscViewer
729 
730     Input Parameter:
731 .   viewer - the PetscViewer (created with PetscViewerDrawOpen())
732 
733     Output Paramters:
734 +   nbounds - number of plots that can be made with this viewer, for example the dof passed to DMDACreate()
735 -   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, .....
736 
737     Level: intermediate
738 
739    Concepts: drawing^accessing PetscDraw context from PetscViewer
740    Concepts: graphics
741 
742 .seealso: PetscViewerDrawGetLG(), PetscViewerDrawGetAxis(), PetscViewerDrawOpen(), PetscViewerDrawSetBounds()
743 @*/
744 PetscErrorCode  PetscViewerDrawGetBounds(PetscViewer viewer,PetscInt *nbounds,const PetscReal **bounds)
745 {
746   PetscViewer_Draw *vdraw = (PetscViewer_Draw*)viewer->data;
747 
748   PetscFunctionBegin;
749   PetscValidHeaderSpecific(viewer,PETSC_VIEWER_CLASSID,1);
750   *nbounds = vdraw->nbounds;
751   *bounds  = vdraw->bounds;
752   PetscFunctionReturn(0);
753 }
754