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