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