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