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