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