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