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