xref: /petsc/src/sys/classes/viewer/impls/draw/drawv.c (revision 785e854f82a3c614b452fca2cf5ad4f2afe8bdde)
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);CHKERRQ(ierr);
26   PetscFunctionReturn(0);
27 }
28 
29 #undef __FUNCT__
30 #define __FUNCT__ "PetscViewerFlush_Draw"
31 PetscErrorCode PetscViewerFlush_Draw(PetscViewer v)
32 {
33   PetscErrorCode   ierr;
34   PetscInt         i;
35   PetscViewer_Draw *vdraw = (PetscViewer_Draw*)v->data;
36 
37   PetscFunctionBegin;
38   for (i=0; i<vdraw->draw_max; i++) {
39     if (vdraw->draw[i]) {ierr = PetscDrawSynchronizedFlush(vdraw->draw[i]);CHKERRQ(ierr);}
40   }
41   PetscFunctionReturn(0);
42 }
43 
44 #undef __FUNCT__
45 #define __FUNCT__ "PetscViewerDrawGetDraw"
46 /*@C
47     PetscViewerDrawGetDraw - Returns PetscDraw object from PetscViewer object.
48     This PetscDraw object may then be used to perform graphics using
49     PetscDrawXXX() commands.
50 
51     Not collective (but PetscDraw returned will be parallel object if PetscViewer is)
52 
53     Input Parameters:
54 +  viewer - the PetscViewer (created with PetscViewerDrawOpen())
55 -   windownumber - indicates which subwindow (usually 0)
56 
57     Ouput Parameter:
58 .   draw - the draw object
59 
60     Level: intermediate
61 
62    Concepts: drawing^accessing PetscDraw context from PetscViewer
63    Concepts: graphics
64 
65 .seealso: PetscViewerDrawGetLG(), PetscViewerDrawGetAxis(), PetscViewerDrawOpen()
66 @*/
67 PetscErrorCode  PetscViewerDrawGetDraw(PetscViewer viewer,PetscInt windownumber,PetscDraw *draw)
68 {
69   PetscViewer_Draw *vdraw = (PetscViewer_Draw*)viewer->data;
70   PetscErrorCode   ierr;
71   PetscBool        isdraw;
72   char             *title;
73 
74   PetscFunctionBegin;
75   PetscValidHeaderSpecific(viewer,PETSC_VIEWER_CLASSID,1);
76   if (draw) PetscValidPointer(draw,3);
77   ierr = PetscObjectTypeCompare((PetscObject)viewer,PETSCVIEWERDRAW,&isdraw);CHKERRQ(ierr);
78   if (!isdraw) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_WRONG,"Must be draw type PetscViewer");
79   if (windownumber < 0) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_OUTOFRANGE,"Window number cannot be negative");
80   windownumber += vdraw->draw_base;
81   if (windownumber >= vdraw->draw_max) {
82     /* allocate twice as many slots as needed */
83     PetscInt      draw_max  = vdraw->draw_max;
84     PetscDraw     *tdraw    = vdraw->draw;
85     PetscDrawLG   *drawlg   = vdraw->drawlg;
86     PetscDrawAxis *drawaxis = vdraw->drawaxis;
87 
88     vdraw->draw_max = 2*windownumber;
89 
90     ierr = PetscMalloc3(vdraw->draw_max,&vdraw->draw,vdraw->draw_max,&vdraw->drawlg,vdraw->draw_max,&vdraw->drawaxis);CHKERRQ(ierr);
91     ierr = PetscMemzero(vdraw->draw,vdraw->draw_max*sizeof(PetscDraw));CHKERRQ(ierr);
92     ierr = PetscMemzero(vdraw->drawlg,vdraw->draw_max*sizeof(PetscDrawLG));CHKERRQ(ierr);
93     ierr = PetscMemzero(vdraw->drawaxis,vdraw->draw_max*sizeof(PetscDrawAxis));CHKERRQ(ierr);
94 
95     ierr = PetscMemcpy(vdraw->draw,tdraw,draw_max*sizeof(PetscDraw));CHKERRQ(ierr);
96     ierr = PetscMemcpy(vdraw->drawlg,drawlg,draw_max*sizeof(PetscDrawLG));CHKERRQ(ierr);
97     ierr = PetscMemcpy(vdraw->drawaxis,drawaxis,draw_max*sizeof(PetscDrawAxis));CHKERRQ(ierr);
98 
99     ierr = PetscFree3(tdraw,drawlg,drawaxis);CHKERRQ(ierr);
100   }
101 
102   if (!vdraw->draw[windownumber]) {
103     if (!windownumber) title = vdraw->title;
104     else {
105       char tmp_str[128];
106       ierr  = PetscSNPrintf(tmp_str, 128, "%s:%d", vdraw->title,windownumber);CHKERRQ(ierr);
107       title = tmp_str;
108     }
109     ierr = PetscDrawCreate(PetscObjectComm((PetscObject)viewer),vdraw->display,title,PETSC_DECIDE,PETSC_DECIDE,vdraw->w,vdraw->h,&vdraw->draw[windownumber]);CHKERRQ(ierr);
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__ "PetscViewerDrawOpen"
305 /*@C
306    PetscViewerDrawOpen - Opens a window for use as a PetscViewer. If you want to
307    do graphics in this window, you must call PetscViewerDrawGetDraw() and
308    perform the graphics on the PetscDraw object.
309 
310    Collective on MPI_Comm
311 
312    Input Parameters:
313 +  comm - communicator that will share window
314 .  display - the X display on which to open, or null for the local machine
315 .  title - the title to put in the title bar, or null for no title
316 .  x, y - the screen coordinates of the upper left corner of window, or use PETSC_DECIDE
317 -  w, h - window width and height in pixels, or may use PETSC_DECIDE or PETSC_DRAW_FULL_SIZE, PETSC_DRAW_HALF_SIZE,
318           PETSC_DRAW_THIRD_SIZE, PETSC_DRAW_QUARTER_SIZE
319 
320    Output Parameters:
321 . viewer - the PetscViewer
322 
323    Format Options:
324 +  PETSC_VIEWER_DRAW_BASIC - displays with basic format
325 -  PETSC_VIEWER_DRAW_LG    - displays using a line graph
326 
327    Options Database Keys:
328    PetscViewerDrawOpen() calls PetscDrawCreate(), so see the manual page for
329    PetscDrawCreate() for runtime options, including
330 +  -draw_type x or null
331 .  -nox - Disables all x-windows output
332 .  -display <name> - Specifies name of machine for the X display
333 .  -geometry <x,y,w,h> - allows setting the window location and size
334 -  -draw_pause <pause> - Sets time (in seconds) that the
335      program pauses after PetscDrawPause() has been called
336      (0 is default, -1 implies until user input).
337 
338    Level: beginner
339 
340    Note for Fortran Programmers:
341    Whenever indicating null character data in a Fortran code,
342    NULL_CHARACTER must be employed; using NULL is not
343    correct for character data!  Thus, NULL_CHARACTER can be
344    used for the display and title input parameters.
345 
346   Concepts: graphics^opening PetscViewer
347   Concepts: drawing^opening PetscViewer
348 
349 
350 .seealso: PetscDrawCreate(), PetscViewerDestroy(), PetscViewerDrawGetDraw(), PetscViewerCreate(), PETSC_VIEWER_DRAW_,
351           PETSC_VIEWER_DRAW_WORLD, PETSC_VIEWER_DRAW_SELF
352 @*/
353 PetscErrorCode  PetscViewerDrawOpen(MPI_Comm comm,const char display[],const char title[],int x,int y,int w,int h,PetscViewer *viewer)
354 {
355   PetscErrorCode ierr;
356 
357   PetscFunctionBegin;
358   ierr = PetscViewerCreate(comm,viewer);CHKERRQ(ierr);
359   ierr = PetscViewerSetType(*viewer,PETSCVIEWERDRAW);CHKERRQ(ierr);
360   ierr = PetscViewerDrawSetInfo(*viewer,display,title,x,y,w,h);CHKERRQ(ierr);
361   PetscFunctionReturn(0);
362 }
363 
364 #undef __FUNCT__
365 #define __FUNCT__ "PetscViewerGetSingleton_Draw"
366 PetscErrorCode PetscViewerGetSingleton_Draw(PetscViewer viewer,PetscViewer *sviewer)
367 {
368   PetscErrorCode   ierr;
369   PetscMPIInt      rank;
370   PetscInt         i;
371   PetscViewer_Draw *vdraw = (PetscViewer_Draw*)viewer->data,*vsdraw;
372 
373   PetscFunctionBegin;
374   if (vdraw->singleton_made) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ORDER,"Trying to get singleton without first restoring previous");
375 
376   /* only processor zero can use the PetscViewer draw singleton */
377   ierr = MPI_Comm_rank(PetscObjectComm((PetscObject)viewer),&rank);CHKERRQ(ierr);
378   if (!rank) {
379     ierr   = PetscViewerCreate(PETSC_COMM_SELF,sviewer);CHKERRQ(ierr);
380     ierr   = PetscViewerSetType(*sviewer,PETSCVIEWERDRAW);CHKERRQ(ierr);
381     vsdraw = (PetscViewer_Draw*)(*sviewer)->data;
382     for (i=0; i<vdraw->draw_max; i++) {
383       if (vdraw->draw[i]) {
384         ierr = PetscDrawGetSingleton(vdraw->draw[i],&vsdraw->draw[i]);CHKERRQ(ierr);
385       }
386     }
387   }
388   vdraw->singleton_made = PETSC_TRUE;
389   PetscFunctionReturn(0);
390 }
391 
392 #undef __FUNCT__
393 #define __FUNCT__ "PetscViewerRestoreSingleton_Draw"
394 PetscErrorCode PetscViewerRestoreSingleton_Draw(PetscViewer viewer,PetscViewer *sviewer)
395 {
396   PetscErrorCode   ierr;
397   PetscMPIInt      rank;
398   PetscInt         i;
399   PetscViewer_Draw *vdraw = (PetscViewer_Draw*)viewer->data,*vsdraw;
400 
401   PetscFunctionBegin;
402   if (!vdraw->singleton_made) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ORDER,"Trying to restore a singleton that was not gotten");
403   ierr = MPI_Comm_rank(PetscObjectComm((PetscObject)viewer),&rank);CHKERRQ(ierr);
404   if (!rank) {
405     vsdraw = (PetscViewer_Draw*)(*sviewer)->data;
406     for (i=0; i<vdraw->draw_max; i++) {
407       if (vdraw->draw[i] && vsdraw->draw[i]) {
408         ierr = PetscDrawRestoreSingleton(vdraw->draw[i],&vsdraw->draw[i]);CHKERRQ(ierr);
409       }
410     }
411     ierr = PetscFree3(vsdraw->draw,vsdraw->drawlg,vsdraw->drawaxis);CHKERRQ(ierr);
412     ierr = PetscFree((*sviewer)->data);CHKERRQ(ierr);
413     ierr = PetscHeaderDestroy(sviewer);CHKERRQ(ierr);
414   }
415   vdraw->singleton_made = PETSC_FALSE;
416   PetscFunctionReturn(0);
417 }
418 
419 #undef __FUNCT__
420 #define __FUNCT__ "PetscViewerSetFromOptions_Draw"
421 PetscErrorCode PetscViewerSetFromOptions_Draw(PetscViewer v)
422 {
423   PetscErrorCode ierr;
424   PetscReal      bounds[16];
425   PetscInt       nbounds = 16;
426   PetscBool      flg;
427 
428   PetscFunctionBegin;
429   ierr = PetscOptionsHead("Draw PetscViewer Options");CHKERRQ(ierr);
430   ierr = PetscOptionsRealArray("-draw_bounds","Bounds to put on plots axis","PetscViewerDrawSetBounds",bounds,&nbounds,&flg);CHKERRQ(ierr);
431   if (flg) {
432     ierr = PetscViewerDrawSetBounds(v,nbounds/2,bounds);CHKERRQ(ierr);
433   }
434 
435   ierr = PetscOptionsTail();CHKERRQ(ierr);
436   PetscFunctionReturn(0);
437 }
438 
439 #undef __FUNCT__
440 #define __FUNCT__ "PetscViewerView_Draw"
441 PetscErrorCode PetscViewerView_Draw(PetscViewer viewer,PetscViewer v)
442 {
443   PetscErrorCode   ierr;
444   PetscDraw        draw;
445   PetscInt         i;
446   PetscViewer_Draw *vdraw = (PetscViewer_Draw*)viewer->data;
447 
448   PetscFunctionBegin;
449   /*  If the PetscViewer has just been created then no vdraw->draw yet
450       exists so this will not actually call the viewer on any draws. */
451   for (i=0; i<vdraw->draw_base; i++) {
452     if (vdraw->draw[i]) {
453       ierr = PetscViewerDrawGetDraw(viewer,i,&draw);CHKERRQ(ierr);
454       ierr = PetscDrawView(draw,v);CHKERRQ(ierr);
455     }
456   }
457   PetscFunctionReturn(0);
458 }
459 
460 #undef __FUNCT__
461 #define __FUNCT__ "PetscViewerCreate_Draw"
462 PETSC_EXTERN PetscErrorCode PetscViewerCreate_Draw(PetscViewer viewer)
463 {
464   PetscInt         i;
465   PetscErrorCode   ierr;
466   PetscViewer_Draw *vdraw;
467 
468   PetscFunctionBegin;
469   ierr         = PetscNewLog(viewer,PetscViewer_Draw,&vdraw);CHKERRQ(ierr);
470   viewer->data = (void*)vdraw;
471 
472   viewer->ops->flush            = PetscViewerFlush_Draw;
473   viewer->ops->view             = PetscViewerView_Draw;
474   viewer->ops->destroy          = PetscViewerDestroy_Draw;
475   viewer->ops->setfromoptions   = PetscViewerSetFromOptions_Draw;
476   viewer->ops->getsingleton     = PetscViewerGetSingleton_Draw;
477   viewer->ops->restoresingleton = PetscViewerRestoreSingleton_Draw;
478 
479   /* these are created on the fly if requested */
480   vdraw->draw_max  = 5;
481   vdraw->draw_base = 0;
482   vdraw->w         = PETSC_DECIDE;
483   vdraw->h         = PETSC_DECIDE;
484 
485   ierr = PetscMalloc3(vdraw->draw_max,&vdraw->draw,vdraw->draw_max,&vdraw->drawlg,vdraw->draw_max,&vdraw->drawaxis);CHKERRQ(ierr);
486   ierr = PetscMemzero(vdraw->draw,vdraw->draw_max*sizeof(PetscDraw));CHKERRQ(ierr);
487   ierr = PetscMemzero(vdraw->drawlg,vdraw->draw_max*sizeof(PetscDrawLG));CHKERRQ(ierr);
488   ierr = PetscMemzero(vdraw->drawaxis,vdraw->draw_max*sizeof(PetscDrawAxis));CHKERRQ(ierr);
489   for (i=0; i<vdraw->draw_max; i++) {
490     vdraw->draw[i]     = 0;
491     vdraw->drawlg[i]   = 0;
492     vdraw->drawaxis[i] = 0;
493   }
494   vdraw->singleton_made = PETSC_FALSE;
495   PetscFunctionReturn(0);
496 }
497 
498 #undef __FUNCT__
499 #define __FUNCT__ "PetscViewerDrawClear"
500 /*@
501     PetscViewerDrawClear - Clears a PetscDraw graphic associated with a PetscViewer.
502 
503     Not Collective
504 
505     Input Parameter:
506 .  viewer - the PetscViewer
507 
508     Level: intermediate
509 
510 .seealso: PetscViewerDrawOpen(), PetscViewerDrawGetDraw(),
511 
512 @*/
513 PetscErrorCode  PetscViewerDrawClear(PetscViewer viewer)
514 {
515   PetscErrorCode   ierr;
516   PetscInt         i;
517   PetscBool        isdraw;
518   PetscViewer_Draw *vdraw;
519 
520   PetscFunctionBegin;
521   ierr = PetscObjectTypeCompare((PetscObject)viewer,PETSCVIEWERDRAW,&isdraw);CHKERRQ(ierr);
522   if (isdraw) {
523     vdraw = (PetscViewer_Draw*)viewer->data;
524     for (i=0; i<vdraw->draw_max; i++) {
525       if (vdraw->draw[i]) {ierr = PetscDrawClear(vdraw->draw[i]);CHKERRQ(ierr);}
526     }
527   }
528   PetscFunctionReturn(0);
529 }
530 
531 #undef __FUNCT__
532 #define __FUNCT__ "PetscViewerDrawGetPause"
533 /*@
534     PetscViewerDrawGetPause - Gets a pause for the first present draw
535 
536     Not Collective
537 
538     Input Parameter:
539 .  viewer - the PetscViewer
540 
541     Output Parameter:
542 .  pause - the pause value
543 
544     Level: intermediate
545 
546 .seealso: PetscViewerDrawOpen(), PetscViewerDrawGetDraw(),
547 
548 @*/
549 PetscErrorCode  PetscViewerDrawGetPause(PetscViewer viewer,PetscReal *pause)
550 {
551   PetscErrorCode   ierr;
552   PetscInt         i;
553   PetscBool        isdraw;
554   PetscViewer_Draw *vdraw;
555   PetscDraw        draw;
556 
557   PetscFunctionBegin;
558   ierr   = PetscObjectTypeCompare((PetscObject)viewer,PETSCVIEWERDRAW,&isdraw);CHKERRQ(ierr);
559   *pause = 0.0;
560   if (isdraw) {
561     vdraw = (PetscViewer_Draw*)viewer->data;
562     for (i=0; i<vdraw->draw_max; i++) {
563       if (vdraw->draw[i]) {
564         ierr = PetscDrawGetPause(vdraw->draw[i],pause);CHKERRQ(ierr);
565         PetscFunctionReturn(0);
566       }
567     }
568     /* none exist yet so create one and get its pause */
569     ierr = PetscViewerDrawGetDraw(viewer,0,&draw);CHKERRQ(ierr);
570     ierr = PetscDrawGetPause(vdraw->draw[0],pause);CHKERRQ(ierr);
571   }
572   PetscFunctionReturn(0);
573 }
574 
575 #undef __FUNCT__
576 #define __FUNCT__ "PetscViewerDrawSetPause"
577 /*@
578     PetscViewerDrawSetPause - Sets a pause for each PetscDraw in the viewer
579 
580     Not Collective
581 
582     Input Parameters:
583 +  viewer - the PetscViewer
584 -  pause - the pause value
585 
586     Level: intermediate
587 
588 .seealso: PetscViewerDrawOpen(), PetscViewerDrawGetDraw(),
589 
590 @*/
591 PetscErrorCode  PetscViewerDrawSetPause(PetscViewer viewer,PetscReal pause)
592 {
593   PetscErrorCode   ierr;
594   PetscInt         i;
595   PetscBool        isdraw;
596 
597   PetscFunctionBegin;
598   ierr = PetscObjectTypeCompare((PetscObject)viewer,PETSCVIEWERDRAW,&isdraw);CHKERRQ(ierr);
599   if (isdraw) {
600     PetscViewer_Draw *vdraw = (PetscViewer_Draw*)viewer->data;
601 
602     vdraw->pause = pause;
603     for (i=0; i<vdraw->draw_max; i++) {
604       if (vdraw->draw[i]) {ierr = PetscDrawSetPause(vdraw->draw[i],pause);CHKERRQ(ierr);}
605     }
606   }
607   PetscFunctionReturn(0);
608 }
609 
610 
611 #undef __FUNCT__
612 #define __FUNCT__ "PetscViewerDrawSetHold"
613 /*@
614     PetscViewerDrawSetHold - Holds previous image when drawing new image
615 
616     Not Collective
617 
618     Input Parameters:
619 +  viewer - the PetscViewer
620 -  hold - indicates to hold or not
621 
622     Level: intermediate
623 
624 .seealso: PetscViewerDrawOpen(), PetscViewerDrawGetDraw(),
625 
626 @*/
627 PetscErrorCode  PetscViewerDrawSetHold(PetscViewer viewer,PetscBool hold)
628 {
629   PetscErrorCode   ierr;
630   PetscViewer_Draw *vdraw;
631   PetscBool        isdraw;
632 
633   PetscFunctionBegin;
634   ierr = PetscObjectTypeCompare((PetscObject)viewer,PETSCVIEWERDRAW,&isdraw);CHKERRQ(ierr);
635   if (isdraw) {
636     vdraw       = (PetscViewer_Draw*)viewer->data;
637     vdraw->hold = hold;
638   }
639   PetscFunctionReturn(0);
640 }
641 
642 #undef __FUNCT__
643 #define __FUNCT__ "PetscViewerDrawGetHold"
644 /*@
645     PetscViewerDrawGetHold - Holds previous image when drawing new image
646 
647     Not Collective
648 
649     Input Parameter:
650 .  viewer - the PetscViewer
651 
652     Output Parameter:
653 .  hold - indicates to hold or not
654 
655     Level: intermediate
656 
657 .seealso: PetscViewerDrawOpen(), PetscViewerDrawGetDraw(),
658 
659 @*/
660 PetscErrorCode  PetscViewerDrawGetHold(PetscViewer viewer,PetscBool *hold)
661 {
662   PetscErrorCode   ierr;
663   PetscViewer_Draw *vdraw;
664   PetscBool        isdraw;
665 
666   PetscFunctionBegin;
667   ierr = PetscObjectTypeCompare((PetscObject)viewer,PETSCVIEWERDRAW,&isdraw);CHKERRQ(ierr);
668   if (isdraw) {
669     vdraw = (PetscViewer_Draw*)viewer->data;
670     *hold = vdraw->hold;
671   }
672   PetscFunctionReturn(0);
673 }
674 
675 /* ---------------------------------------------------------------------*/
676 /*
677     The variable Petsc_Viewer_Draw_keyval is used to indicate an MPI attribute that
678   is attached to a communicator, in this case the attribute is a PetscViewer.
679 */
680 static PetscMPIInt Petsc_Viewer_Draw_keyval = MPI_KEYVAL_INVALID;
681 
682 #undef __FUNCT__
683 #define __FUNCT__ "PETSC_VIEWER_DRAW_"
684 /*@C
685     PETSC_VIEWER_DRAW_ - Creates a window PetscViewer shared by all processors
686                      in a communicator.
687 
688      Collective on MPI_Comm
689 
690      Input Parameter:
691 .    comm - the MPI communicator to share the window PetscViewer
692 
693      Level: intermediate
694 
695      Notes:
696      Unlike almost all other PETSc routines, PETSC_VIEWER_DRAW_ does not return
697      an error code.  The window is usually used in the form
698 $       XXXView(XXX object,PETSC_VIEWER_DRAW_(comm));
699 
700 .seealso: PETSC_VIEWER_DRAW_WORLD, PETSC_VIEWER_DRAW_SELF, PetscViewerDrawOpen(),
701 @*/
702 PetscViewer  PETSC_VIEWER_DRAW_(MPI_Comm comm)
703 {
704   PetscErrorCode ierr;
705   PetscMPIInt    flag;
706   PetscViewer    viewer;
707   MPI_Comm       ncomm;
708 
709   PetscFunctionBegin;
710   ierr = PetscCommDuplicate(comm,&ncomm,NULL);if (ierr) {PetscError(PETSC_COMM_SELF,__LINE__,"PETSC_VIEWER_DRAW_",__FILE__,PETSC_ERR_PLIB,PETSC_ERROR_INITIAL," ");PetscFunctionReturn(0);}
711   if (Petsc_Viewer_Draw_keyval == MPI_KEYVAL_INVALID) {
712     ierr = MPI_Keyval_create(MPI_NULL_COPY_FN,MPI_NULL_DELETE_FN,&Petsc_Viewer_Draw_keyval,0);
713     if (ierr) {PetscError(PETSC_COMM_SELF,__LINE__,"PETSC_VIEWER_DRAW_",__FILE__,PETSC_ERR_PLIB,PETSC_ERROR_INITIAL," ");PetscFunctionReturn(0);}
714   }
715   ierr = MPI_Attr_get(ncomm,Petsc_Viewer_Draw_keyval,(void**)&viewer,&flag);
716   if (ierr) {PetscError(PETSC_COMM_SELF,__LINE__,"PETSC_VIEWER_DRAW_",__FILE__,PETSC_ERR_PLIB,PETSC_ERROR_INITIAL," ");PetscFunctionReturn(0);}
717   if (!flag) { /* PetscViewer not yet created */
718     ierr = PetscViewerDrawOpen(ncomm,0,0,PETSC_DECIDE,PETSC_DECIDE,300,300,&viewer);
719     if (ierr) {PetscError(PETSC_COMM_SELF,__LINE__,"PETSC_VIEWER_DRAW_",__FILE__,PETSC_ERR_PLIB,PETSC_ERROR_INITIAL," ");PetscFunctionReturn(0);}
720     ierr = PetscObjectRegisterDestroy((PetscObject)viewer);
721     if (ierr) {PetscError(PETSC_COMM_SELF,__LINE__,"PETSC_VIEWER_DRAW_",__FILE__,PETSC_ERR_PLIB,PETSC_ERROR_INITIAL," ");PetscFunctionReturn(0);}
722     ierr = MPI_Attr_put(ncomm,Petsc_Viewer_Draw_keyval,(void*)viewer);
723     if (ierr) {PetscError(PETSC_COMM_SELF,__LINE__,"PETSC_VIEWER_DRAW_",__FILE__,PETSC_ERR_PLIB,PETSC_ERROR_INITIAL," ");PetscFunctionReturn(0);}
724   }
725   ierr = PetscCommDestroy(&ncomm);
726   if (ierr) {PetscError(PETSC_COMM_SELF,__LINE__,"PETSC_VIEWER_DRAW_",__FILE__,PETSC_ERR_PLIB,PETSC_ERROR_INITIAL," ");PetscFunctionReturn(0);}
727   PetscFunctionReturn(viewer);
728 }
729 
730 #undef __FUNCT__
731 #define __FUNCT__ "PetscViewerDrawSetBounds"
732 /*@
733     PetscViewerDrawSetBounds - sets the upper and lower bounds to be used in plotting
734 
735     Collective on PetscViewer
736 
737     Input Parameters:
738 +   viewer - the PetscViewer (created with PetscViewerDrawOpen())
739 .   nbounds - number of plots that can be made with this viewer, for example the dof passed to DMDACreate()
740 -   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, .....
741 
742 
743     Options Database:
744 .   -draw_bounds  minF0,maxF0,minF1,maxF1
745 
746     Level: intermediate
747 
748     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
749       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
750       this viewer. Otherwise the color to physical value meaning changes with each new image if this is not set.
751 
752    Concepts: drawing^accessing PetscDraw context from PetscViewer
753    Concepts: graphics
754 
755 .seealso: PetscViewerDrawGetLG(), PetscViewerDrawGetAxis(), PetscViewerDrawOpen()
756 @*/
757 PetscErrorCode  PetscViewerDrawSetBounds(PetscViewer viewer,PetscInt nbounds,const PetscReal *bounds)
758 {
759   PetscViewer_Draw *vdraw = (PetscViewer_Draw*)viewer->data;
760   PetscErrorCode   ierr;
761 
762 
763   PetscFunctionBegin;
764   PetscValidHeaderSpecific(viewer,PETSC_VIEWER_CLASSID,1);
765   vdraw->nbounds = nbounds;
766 
767   ierr = PetscMalloc1(2*nbounds,&vdraw->bounds);CHKERRQ(ierr);
768   ierr = PetscMemcpy(vdraw->bounds,bounds,2*nbounds*sizeof(PetscReal));CHKERRQ(ierr);
769   PetscFunctionReturn(0);
770 }
771 
772 #undef __FUNCT__
773 #define __FUNCT__ "PetscViewerDrawGetBounds"
774 /*@C
775     PetscViewerDrawGetBounds - gets the upper and lower bounds to be used in plotting set with PetscViewerDrawSetBounds()
776 
777     Collective on PetscViewer
778 
779     Input Parameter:
780 .   viewer - the PetscViewer (created with PetscViewerDrawOpen())
781 
782     Output Paramters:
783 +   nbounds - number of plots that can be made with this viewer, for example the dof passed to DMDACreate()
784 -   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, .....
785 
786     Level: intermediate
787 
788    Concepts: drawing^accessing PetscDraw context from PetscViewer
789    Concepts: graphics
790 
791 .seealso: PetscViewerDrawGetLG(), PetscViewerDrawGetAxis(), PetscViewerDrawOpen(), PetscViewerDrawSetBounds()
792 @*/
793 PetscErrorCode  PetscViewerDrawGetBounds(PetscViewer viewer,PetscInt *nbounds,const PetscReal **bounds)
794 {
795   PetscViewer_Draw *vdraw = (PetscViewer_Draw*)viewer->data;
796 
797   PetscFunctionBegin;
798   PetscValidHeaderSpecific(viewer,PETSC_VIEWER_CLASSID,1);
799   *nbounds = vdraw->nbounds;
800   *bounds  = vdraw->bounds;
801   PetscFunctionReturn(0);
802 }
803