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