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