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