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