xref: /petsc/src/sys/classes/viewer/impls/draw/drawv.c (revision 1f49e1f73dad464759f4f6edc53861b4418ff9ce)
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 /*@C
346    PetscViewerDrawOpen - Opens a window for use as a PetscViewer. If you want to
347    do graphics in this window, you must call PetscViewerDrawGetDraw() and
348    perform the graphics on the PetscDraw object.
349 
350    Collective on MPI_Comm
351 
352    Input Parameters:
353 +  comm - communicator that will share window
354 .  display - the X display on which to open, or null for the local machine
355 .  title - the title to put in the title bar, or null for no title
356 .  x, y - the screen coordinates of the upper left corner of window, or use PETSC_DECIDE
357 -  w, h - window width and height in pixels, or may use PETSC_DECIDE or PETSC_DRAW_FULL_SIZE, PETSC_DRAW_HALF_SIZE,
358           PETSC_DRAW_THIRD_SIZE, PETSC_DRAW_QUARTER_SIZE
359 
360    Output Parameters:
361 . viewer - the PetscViewer
362 
363    Format Options:
364 +  PETSC_VIEWER_DRAW_BASIC - displays with basic format
365 -  PETSC_VIEWER_DRAW_LG    - displays using a line graph
366 
367    Options Database Keys:
368    PetscViewerDrawOpen() calls PetscDrawCreate(), so see the manual page for
369    PetscDrawCreate() for runtime options, including
370 +  -draw_type x or null
371 .  -nox - Disables all x-windows output
372 .  -display <name> - Specifies name of machine for the X display
373 .  -geometry <x,y,w,h> - allows setting the window location and size
374 -  -draw_pause <pause> - Sets time (in seconds) that the
375      program pauses after PetscDrawPause() has been called
376      (0 is default, -1 implies until user input).
377 
378    Level: beginner
379 
380    Note for Fortran Programmers:
381    Whenever indicating null character data in a Fortran code,
382    NULL_CHARACTER must be employed; using NULL is not
383    correct for character data!  Thus, NULL_CHARACTER can be
384    used for the display and title input parameters.
385 
386   Concepts: graphics^opening PetscViewer
387   Concepts: drawing^opening PetscViewer
388 
389 
390 .seealso: PetscDrawCreate(), PetscViewerDestroy(), PetscViewerDrawGetDraw(), PetscViewerCreate(), PETSC_VIEWER_DRAW_,
391           PETSC_VIEWER_DRAW_WORLD, PETSC_VIEWER_DRAW_SELF
392 @*/
393 PetscErrorCode  PetscViewerDrawOpen(MPI_Comm comm,const char display[],const char title[],int x,int y,int w,int h,PetscViewer *viewer)
394 {
395   PetscErrorCode ierr;
396 
397   PetscFunctionBegin;
398   ierr = PetscViewerCreate(comm,viewer);CHKERRQ(ierr);
399   ierr = PetscViewerSetType(*viewer,PETSCVIEWERDRAW);CHKERRQ(ierr);
400   ierr = PetscViewerDrawSetInfo(*viewer,display,title,x,y,w,h);CHKERRQ(ierr);
401   PetscFunctionReturn(0);
402 }
403 
404 PetscErrorCode PetscViewerGetSubViewer_Draw(PetscViewer viewer,MPI_Comm comm,PetscViewer *sviewer)
405 {
406   PetscErrorCode   ierr;
407   PetscMPIInt      rank;
408   PetscInt         i;
409   PetscViewer_Draw *vdraw = (PetscViewer_Draw*)viewer->data,*svdraw;
410 
411   PetscFunctionBegin;
412   if (vdraw->singleton_made) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ORDER,"Trying to get SubViewer without first restoring previous");
413   /* only processor zero can use the PetscViewer draw singleton */
414   if (*sviewer) *sviewer = NULL;
415   ierr = MPI_Comm_rank(PetscObjectComm((PetscObject)viewer),&rank);CHKERRQ(ierr);
416   if (!rank) {
417     ierr = PetscViewerCreate(PETSC_COMM_SELF,sviewer);CHKERRQ(ierr);
418     ierr = PetscViewerSetType(*sviewer,PETSCVIEWERDRAW);CHKERRQ(ierr);
419     svdraw = (PetscViewer_Draw*)(*sviewer)->data;
420     (*sviewer)->format = viewer->format;
421     for (i=0; i<vdraw->draw_max; i++) { /* XXX this is wrong if svdraw->draw_max (initially 5) < vdraw->draw_max */
422       if (vdraw->draw[i]) {ierr = PetscDrawGetSingleton(vdraw->draw[i],&svdraw->draw[i]);CHKERRQ(ierr);}
423     }
424   }
425   vdraw->singleton_made = PETSC_TRUE;
426   PetscFunctionReturn(0);
427 }
428 
429 PetscErrorCode PetscViewerRestoreSubViewer_Draw(PetscViewer viewer,MPI_Comm comm,PetscViewer *sviewer)
430 {
431   PetscErrorCode   ierr;
432   PetscMPIInt      rank;
433   PetscInt         i;
434   PetscViewer_Draw *vdraw = (PetscViewer_Draw*)viewer->data,*svdraw;
435 
436   PetscFunctionBegin;
437   if (!vdraw->singleton_made) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ORDER,"Trying to restore a singleton that was not gotten");
438   ierr = MPI_Comm_rank(PetscObjectComm((PetscObject)viewer),&rank);CHKERRQ(ierr);
439   if (!rank) {
440     svdraw = (PetscViewer_Draw*)(*sviewer)->data;
441     for (i=0; i<vdraw->draw_max; i++) {
442       if (vdraw->draw[i] && svdraw->draw[i]) {
443         ierr = PetscDrawRestoreSingleton(vdraw->draw[i],&svdraw->draw[i]);CHKERRQ(ierr);
444       }
445     }
446     ierr = PetscFree3(svdraw->draw,svdraw->drawlg,svdraw->drawaxis);CHKERRQ(ierr);
447     ierr = PetscFree((*sviewer)->data);CHKERRQ(ierr);
448     ierr = PetscHeaderDestroy(sviewer);CHKERRQ(ierr);
449   }
450   vdraw->singleton_made = PETSC_FALSE;
451   PetscFunctionReturn(0);
452 }
453 
454 PetscErrorCode PetscViewerSetFromOptions_Draw(PetscOptionItems *PetscOptionsObject,PetscViewer v)
455 {
456   PetscErrorCode ierr;
457   PetscReal      bounds[16];
458   PetscInt       nbounds = 16;
459   PetscBool      flg;
460 
461   PetscFunctionBegin;
462   ierr = PetscOptionsHead(PetscOptionsObject,"Draw PetscViewer Options");CHKERRQ(ierr);
463   ierr = PetscOptionsRealArray("-draw_bounds","Bounds to put on plots axis","PetscViewerDrawSetBounds",bounds,&nbounds,&flg);CHKERRQ(ierr);
464   if (flg) {
465     ierr = PetscViewerDrawSetBounds(v,nbounds/2,bounds);CHKERRQ(ierr);
466   }
467   ierr = PetscOptionsTail();CHKERRQ(ierr);
468   PetscFunctionReturn(0);
469 }
470 
471 PetscErrorCode PetscViewerView_Draw(PetscViewer viewer,PetscViewer v)
472 {
473   PetscErrorCode   ierr;
474   PetscDraw        draw;
475   PetscInt         i;
476   PetscViewer_Draw *vdraw = (PetscViewer_Draw*)viewer->data;
477 
478   PetscFunctionBegin;
479   /*  If the PetscViewer has just been created then no vdraw->draw yet
480       exists so this will not actually call the viewer on any draws. */
481   for (i=0; i<vdraw->draw_base; i++) {
482     if (vdraw->draw[i]) {
483       ierr = PetscViewerDrawGetDraw(viewer,i,&draw);CHKERRQ(ierr);
484       ierr = PetscDrawView(draw,v);CHKERRQ(ierr);
485     }
486   }
487   PetscFunctionReturn(0);
488 }
489 
490 /*MC
491    PETSCVIEWERDRAW - A viewer that generates graphics, either to the screen or a file
492 
493 
494 .seealso:  PetscViewerDrawOpen(), PetscViewerDrawGetDraw(), PETSC_VIEWER_DRAW_(),PETSC_VIEWER_DRAW_SELF, PETSC_VIEWER_DRAW_WORLD,
495            PetscViewerCreate(), PetscViewerASCIIOpen(), PetscViewerBinaryOpen(), PETSCVIEWERBINARY,
496            PetscViewerMatlabOpen(), VecView(), DMView(), PetscViewerMatlabPutArray(), PETSCVIEWERASCII, PETSCVIEWERMATLAB,
497            PetscViewerFileSetName(), PetscViewerFileSetMode(), PetscViewerFormat, PetscViewerType, PetscViewerSetType()
498 
499   Level: beginner
500 
501 M*/
502 PETSC_EXTERN PetscErrorCode PetscViewerCreate_Draw(PetscViewer viewer)
503 {
504   PetscErrorCode   ierr;
505   PetscViewer_Draw *vdraw;
506 
507   PetscFunctionBegin;
508   ierr = PetscNewLog(viewer,&vdraw);CHKERRQ(ierr);
509   viewer->data = (void*)vdraw;
510 
511   viewer->ops->flush            = PetscViewerFlush_Draw;
512   viewer->ops->view             = PetscViewerView_Draw;
513   viewer->ops->destroy          = PetscViewerDestroy_Draw;
514   viewer->ops->setfromoptions   = PetscViewerSetFromOptions_Draw;
515   viewer->ops->getsubviewer     = PetscViewerGetSubViewer_Draw;
516   viewer->ops->restoresubviewer = PetscViewerRestoreSubViewer_Draw;
517 
518   /* these are created on the fly if requested */
519   vdraw->draw_max  = 5;
520   vdraw->draw_base = 0;
521   vdraw->w         = PETSC_DECIDE;
522   vdraw->h         = PETSC_DECIDE;
523 
524   ierr = PetscCalloc3(vdraw->draw_max,&vdraw->draw,vdraw->draw_max,&vdraw->drawlg,vdraw->draw_max,&vdraw->drawaxis);CHKERRQ(ierr);
525   vdraw->singleton_made = PETSC_FALSE;
526   PetscFunctionReturn(0);
527 }
528 
529 /*@
530     PetscViewerDrawClear - Clears a PetscDraw graphic associated with a PetscViewer.
531 
532     Not Collective
533 
534     Input Parameter:
535 .  viewer - the PetscViewer
536 
537     Level: intermediate
538 
539 .seealso: PetscViewerDrawOpen(), PetscViewerDrawGetDraw(),
540 
541 @*/
542 PetscErrorCode  PetscViewerDrawClear(PetscViewer viewer)
543 {
544   PetscErrorCode   ierr;
545   PetscViewer_Draw *vdraw;
546   PetscBool        isdraw;
547   PetscInt         i;
548 
549   PetscFunctionBegin;
550   PetscValidHeaderSpecific(viewer,PETSC_VIEWER_CLASSID,1);
551   ierr = PetscObjectTypeCompare((PetscObject)viewer,PETSCVIEWERDRAW,&isdraw);CHKERRQ(ierr);
552   if (!isdraw) PetscFunctionReturn(0);
553   vdraw = (PetscViewer_Draw*)viewer->data;
554 
555   for (i=0; i<vdraw->draw_max; i++) {
556     if (vdraw->draw[i]) {ierr = PetscDrawClear(vdraw->draw[i]);CHKERRQ(ierr);}
557   }
558   PetscFunctionReturn(0);
559 }
560 
561 /*@
562     PetscViewerDrawGetPause - Gets a pause for the first present draw
563 
564     Not Collective
565 
566     Input Parameter:
567 .  viewer - the PetscViewer
568 
569     Output Parameter:
570 .  pause - the pause value
571 
572     Level: intermediate
573 
574 .seealso: PetscViewerDrawOpen(), PetscViewerDrawGetDraw(),
575 
576 @*/
577 PetscErrorCode  PetscViewerDrawGetPause(PetscViewer viewer,PetscReal *pause)
578 {
579   PetscErrorCode   ierr;
580   PetscViewer_Draw *vdraw;
581   PetscBool        isdraw;
582   PetscInt         i;
583   PetscDraw        draw;
584 
585   PetscFunctionBegin;
586   PetscValidHeaderSpecific(viewer,PETSC_VIEWER_CLASSID,1);
587   ierr = PetscObjectTypeCompare((PetscObject)viewer,PETSCVIEWERDRAW,&isdraw);CHKERRQ(ierr);
588   if (!isdraw) {*pause = 0.0; PetscFunctionReturn(0);}
589   vdraw = (PetscViewer_Draw*)viewer->data;
590 
591   for (i=0; i<vdraw->draw_max; i++) {
592     if (vdraw->draw[i]) {
593       ierr = PetscDrawGetPause(vdraw->draw[i],pause);CHKERRQ(ierr);
594       PetscFunctionReturn(0);
595     }
596   }
597   /* none exist yet so create one and get its pause */
598   ierr = PetscViewerDrawGetDraw(viewer,0,&draw);CHKERRQ(ierr);
599   ierr = PetscDrawGetPause(draw,pause);CHKERRQ(ierr);
600   PetscFunctionReturn(0);
601 }
602 
603 /*@
604     PetscViewerDrawSetPause - Sets a pause for each PetscDraw in the viewer
605 
606     Not Collective
607 
608     Input Parameters:
609 +  viewer - the PetscViewer
610 -  pause - the pause value
611 
612     Level: intermediate
613 
614 .seealso: PetscViewerDrawOpen(), PetscViewerDrawGetDraw(),
615 
616 @*/
617 PetscErrorCode  PetscViewerDrawSetPause(PetscViewer viewer,PetscReal pause)
618 {
619   PetscErrorCode   ierr;
620   PetscViewer_Draw *vdraw;
621   PetscBool        isdraw;
622   PetscInt         i;
623 
624   PetscFunctionBegin;
625   PetscValidHeaderSpecific(viewer,PETSC_VIEWER_CLASSID,1);
626   ierr = PetscObjectTypeCompare((PetscObject)viewer,PETSCVIEWERDRAW,&isdraw);CHKERRQ(ierr);
627   if (!isdraw) PetscFunctionReturn(0);
628   vdraw = (PetscViewer_Draw*)viewer->data;
629 
630   vdraw->pause = pause;
631   for (i=0; i<vdraw->draw_max; i++) {
632     if (vdraw->draw[i]) {ierr = PetscDrawSetPause(vdraw->draw[i],pause);CHKERRQ(ierr);}
633   }
634   PetscFunctionReturn(0);
635 }
636 
637 
638 /*@
639     PetscViewerDrawSetHold - Holds previous image when drawing new image
640 
641     Not Collective
642 
643     Input Parameters:
644 +  viewer - the PetscViewer
645 -  hold - indicates to hold or not
646 
647     Level: intermediate
648 
649 .seealso: PetscViewerDrawOpen(), PetscViewerDrawGetDraw(),
650 
651 @*/
652 PetscErrorCode  PetscViewerDrawSetHold(PetscViewer viewer,PetscBool hold)
653 {
654   PetscErrorCode   ierr;
655   PetscViewer_Draw *vdraw;
656   PetscBool        isdraw;
657 
658   PetscFunctionBegin;
659   PetscValidHeaderSpecific(viewer,PETSC_VIEWER_CLASSID,1);
660   ierr = PetscObjectTypeCompare((PetscObject)viewer,PETSCVIEWERDRAW,&isdraw);CHKERRQ(ierr);
661   if (!isdraw) PetscFunctionReturn(0);
662   vdraw = (PetscViewer_Draw*)viewer->data;
663 
664   vdraw->hold = hold;
665   PetscFunctionReturn(0);
666 }
667 
668 /*@
669     PetscViewerDrawGetHold - Checks if holds previous image when drawing new image
670 
671     Not Collective
672 
673     Input Parameter:
674 .  viewer - the PetscViewer
675 
676     Output Parameter:
677 .  hold - indicates to hold or not
678 
679     Level: intermediate
680 
681 .seealso: PetscViewerDrawOpen(), PetscViewerDrawGetDraw(),
682 
683 @*/
684 PetscErrorCode  PetscViewerDrawGetHold(PetscViewer viewer,PetscBool *hold)
685 {
686   PetscErrorCode   ierr;
687   PetscViewer_Draw *vdraw;
688   PetscBool        isdraw;
689 
690   PetscFunctionBegin;
691   PetscValidHeaderSpecific(viewer,PETSC_VIEWER_CLASSID,1);
692   ierr = PetscObjectTypeCompare((PetscObject)viewer,PETSCVIEWERDRAW,&isdraw);CHKERRQ(ierr);
693   if (!isdraw) {*hold = PETSC_FALSE; PetscFunctionReturn(0);}
694   vdraw = (PetscViewer_Draw*)viewer->data;
695 
696   *hold = vdraw->hold;
697   PetscFunctionReturn(0);
698 }
699 
700 /* ---------------------------------------------------------------------*/
701 /*
702     The variable Petsc_Viewer_Draw_keyval is used to indicate an MPI attribute that
703   is attached to a communicator, in this case the attribute is a PetscViewer.
704 */
705 PetscMPIInt Petsc_Viewer_Draw_keyval = MPI_KEYVAL_INVALID;
706 
707 /*@C
708     PETSC_VIEWER_DRAW_ - Creates a window PetscViewer shared by all processors
709                      in a communicator.
710 
711      Collective on MPI_Comm
712 
713      Input Parameter:
714 .    comm - the MPI communicator to share the window PetscViewer
715 
716      Level: intermediate
717 
718      Notes:
719      Unlike almost all other PETSc routines, PETSC_VIEWER_DRAW_ does not return
720      an error code.  The window is usually used in the form
721 $       XXXView(XXX object,PETSC_VIEWER_DRAW_(comm));
722 
723 .seealso: PETSC_VIEWER_DRAW_WORLD, PETSC_VIEWER_DRAW_SELF, PetscViewerDrawOpen(),
724 @*/
725 PetscViewer  PETSC_VIEWER_DRAW_(MPI_Comm comm)
726 {
727   PetscErrorCode ierr;
728   PetscMPIInt    flag;
729   PetscViewer    viewer;
730   MPI_Comm       ncomm;
731 
732   PetscFunctionBegin;
733   ierr = PetscCommDuplicate(comm,&ncomm,NULL);if (ierr) {PetscError(PETSC_COMM_SELF,__LINE__,"PETSC_VIEWER_DRAW_",__FILE__,PETSC_ERR_PLIB,PETSC_ERROR_INITIAL," ");PetscFunctionReturn(0);}
734   if (Petsc_Viewer_Draw_keyval == MPI_KEYVAL_INVALID) {
735     ierr = MPI_Comm_create_keyval(MPI_COMM_NULL_COPY_FN,MPI_COMM_NULL_DELETE_FN,&Petsc_Viewer_Draw_keyval,0);
736     if (ierr) {PetscError(PETSC_COMM_SELF,__LINE__,"PETSC_VIEWER_DRAW_",__FILE__,PETSC_ERR_PLIB,PETSC_ERROR_INITIAL," ");PetscFunctionReturn(0);}
737   }
738   ierr = MPI_Comm_get_attr(ncomm,Petsc_Viewer_Draw_keyval,(void**)&viewer,&flag);
739   if (ierr) {PetscError(PETSC_COMM_SELF,__LINE__,"PETSC_VIEWER_DRAW_",__FILE__,PETSC_ERR_PLIB,PETSC_ERROR_INITIAL," ");PetscFunctionReturn(0);}
740   if (!flag) { /* PetscViewer not yet created */
741     ierr = PetscViewerDrawOpen(ncomm,0,0,PETSC_DECIDE,PETSC_DECIDE,300,300,&viewer);
742     if (ierr) {PetscError(PETSC_COMM_SELF,__LINE__,"PETSC_VIEWER_DRAW_",__FILE__,PETSC_ERR_PLIB,PETSC_ERROR_INITIAL," ");PetscFunctionReturn(0);}
743     ierr = PetscObjectRegisterDestroy((PetscObject)viewer);
744     if (ierr) {PetscError(PETSC_COMM_SELF,__LINE__,"PETSC_VIEWER_DRAW_",__FILE__,PETSC_ERR_PLIB,PETSC_ERROR_INITIAL," ");PetscFunctionReturn(0);}
745     ierr = MPI_Comm_set_attr(ncomm,Petsc_Viewer_Draw_keyval,(void*)viewer);
746     if (ierr) {PetscError(PETSC_COMM_SELF,__LINE__,"PETSC_VIEWER_DRAW_",__FILE__,PETSC_ERR_PLIB,PETSC_ERROR_INITIAL," ");PetscFunctionReturn(0);}
747   }
748   ierr = PetscCommDestroy(&ncomm);
749   if (ierr) {PetscError(PETSC_COMM_SELF,__LINE__,"PETSC_VIEWER_DRAW_",__FILE__,PETSC_ERR_PLIB,PETSC_ERROR_INITIAL," ");PetscFunctionReturn(0);}
750   PetscFunctionReturn(viewer);
751 }
752 
753 /*@
754     PetscViewerDrawSetBounds - sets the upper and lower bounds to be used in plotting
755 
756     Collective on PetscViewer
757 
758     Input Parameters:
759 +   viewer - the PetscViewer (created with PetscViewerDrawOpen())
760 .   nbounds - number of plots that can be made with this viewer, for example the dof passed to DMDACreate()
761 -   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, .....
762 
763 
764     Options Database:
765 .   -draw_bounds  minF0,maxF0,minF1,maxF1
766 
767     Level: intermediate
768 
769     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
770       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
771       this viewer. Otherwise the color to physical value meaning changes with each new image if this is not set.
772 
773    Concepts: drawing^accessing PetscDraw context from PetscViewer
774    Concepts: graphics
775 
776 .seealso: PetscViewerDrawGetLG(), PetscViewerDrawGetAxis(), PetscViewerDrawOpen()
777 @*/
778 PetscErrorCode  PetscViewerDrawSetBounds(PetscViewer viewer,PetscInt nbounds,const PetscReal *bounds)
779 {
780   PetscViewer_Draw *vdraw;
781   PetscBool        isdraw;
782   PetscErrorCode   ierr;
783 
784 
785   PetscFunctionBegin;
786   PetscValidHeaderSpecific(viewer,PETSC_VIEWER_CLASSID,1);
787   ierr = PetscObjectTypeCompare((PetscObject)viewer,PETSCVIEWERDRAW,&isdraw);CHKERRQ(ierr);
788   if (!isdraw) PetscFunctionReturn(0);
789   vdraw = (PetscViewer_Draw*)viewer->data;
790 
791   vdraw->nbounds = nbounds;
792   ierr = PetscFree(vdraw->bounds);CHKERRQ(ierr);
793   ierr = PetscMalloc1(2*nbounds,&vdraw->bounds);CHKERRQ(ierr);
794   ierr = PetscMemcpy(vdraw->bounds,bounds,2*nbounds*sizeof(PetscReal));CHKERRQ(ierr);
795   PetscFunctionReturn(0);
796 }
797 
798 /*@C
799     PetscViewerDrawGetBounds - gets the upper and lower bounds to be used in plotting set with PetscViewerDrawSetBounds()
800 
801     Collective on PetscViewer
802 
803     Input Parameter:
804 .   viewer - the PetscViewer (created with PetscViewerDrawOpen())
805 
806     Output Paramters:
807 +   nbounds - number of plots that can be made with this viewer, for example the dof passed to DMDACreate()
808 -   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, .....
809 
810     Level: intermediate
811 
812    Concepts: drawing^accessing PetscDraw context from PetscViewer
813    Concepts: graphics
814 
815 .seealso: PetscViewerDrawGetLG(), PetscViewerDrawGetAxis(), PetscViewerDrawOpen(), PetscViewerDrawSetBounds()
816 @*/
817 PetscErrorCode  PetscViewerDrawGetBounds(PetscViewer viewer,PetscInt *nbounds,const PetscReal **bounds)
818 {
819   PetscViewer_Draw *vdraw;
820   PetscBool        isdraw;
821   PetscErrorCode   ierr;
822 
823   PetscFunctionBegin;
824   PetscValidHeaderSpecific(viewer,PETSC_VIEWER_CLASSID,1);
825   ierr = PetscObjectTypeCompare((PetscObject)viewer,PETSCVIEWERDRAW,&isdraw);CHKERRQ(ierr);
826   if (!isdraw) {if (nbounds) *nbounds = 0; if (bounds) *bounds = NULL; PetscFunctionReturn(0);}
827   vdraw = (PetscViewer_Draw*)viewer->data;
828 
829   if (nbounds) *nbounds = vdraw->nbounds;
830   if (bounds)  *bounds  = vdraw->bounds;
831   PetscFunctionReturn(0);
832 }
833