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