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