xref: /petsc/src/sys/classes/viewer/impls/draw/drawv.c (revision 8cc058d9cd56c1ccb3be12a47760ddfc446aaffc)
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,PetscDraw,&vdraw->draw,vdraw->draw_max,PetscDrawLG,&vdraw->drawlg,vdraw->draw_max,PetscDrawAxis,&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(viewer,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(viewer,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__ "PetscViewerCreate_Draw"
441 PETSC_EXTERN PetscErrorCode PetscViewerCreate_Draw(PetscViewer viewer)
442 {
443   PetscInt         i;
444   PetscErrorCode   ierr;
445   PetscViewer_Draw *vdraw;
446 
447   PetscFunctionBegin;
448   ierr         = PetscNewLog(viewer,PetscViewer_Draw,&vdraw);CHKERRQ(ierr);
449   viewer->data = (void*)vdraw;
450 
451   viewer->ops->flush            = PetscViewerFlush_Draw;
452   viewer->ops->destroy          = PetscViewerDestroy_Draw;
453   viewer->ops->setfromoptions   = PetscViewerSetFromOptions_Draw;
454   viewer->ops->getsingleton     = PetscViewerGetSingleton_Draw;
455   viewer->ops->restoresingleton = PetscViewerRestoreSingleton_Draw;
456   viewer->format                = PETSC_VIEWER_NOFORMAT;
457 
458   /* these are created on the fly if requested */
459   vdraw->draw_max  = 5;
460   vdraw->draw_base = 0;
461   vdraw->w         = PETSC_DECIDE;
462   vdraw->h         = PETSC_DECIDE;
463 
464   ierr = PetscMalloc3(vdraw->draw_max,PetscDraw,&vdraw->draw,vdraw->draw_max,PetscDrawLG,&vdraw->drawlg,vdraw->draw_max,PetscDrawAxis,&vdraw->drawaxis);CHKERRQ(ierr);
465   ierr = PetscMemzero(vdraw->draw,vdraw->draw_max*sizeof(PetscDraw));CHKERRQ(ierr);
466   ierr = PetscMemzero(vdraw->drawlg,vdraw->draw_max*sizeof(PetscDrawLG));CHKERRQ(ierr);
467   ierr = PetscMemzero(vdraw->drawaxis,vdraw->draw_max*sizeof(PetscDrawAxis));CHKERRQ(ierr);
468   for (i=0; i<vdraw->draw_max; i++) {
469     vdraw->draw[i]     = 0;
470     vdraw->drawlg[i]   = 0;
471     vdraw->drawaxis[i] = 0;
472   }
473   vdraw->singleton_made = PETSC_FALSE;
474   PetscFunctionReturn(0);
475 }
476 
477 #undef __FUNCT__
478 #define __FUNCT__ "PetscViewerDrawClear"
479 /*@
480     PetscViewerDrawClear - Clears a PetscDraw graphic associated with a PetscViewer.
481 
482     Not Collective
483 
484     Input Parameter:
485 .  viewer - the PetscViewer
486 
487     Level: intermediate
488 
489 .seealso: PetscViewerDrawOpen(), PetscViewerDrawGetDraw(),
490 
491 @*/
492 PetscErrorCode  PetscViewerDrawClear(PetscViewer viewer)
493 {
494   PetscErrorCode   ierr;
495   PetscInt         i;
496   PetscBool        isdraw;
497   PetscViewer_Draw *vdraw;
498 
499   PetscFunctionBegin;
500   ierr = PetscObjectTypeCompare((PetscObject)viewer,PETSCVIEWERDRAW,&isdraw);CHKERRQ(ierr);
501   if (isdraw) {
502     vdraw = (PetscViewer_Draw*)viewer->data;
503     for (i=0; i<vdraw->draw_max; i++) {
504       if (vdraw->draw[i]) {ierr = PetscDrawClear(vdraw->draw[i]);CHKERRQ(ierr);}
505     }
506   }
507   PetscFunctionReturn(0);
508 }
509 
510 #undef __FUNCT__
511 #define __FUNCT__ "PetscViewerDrawGetPause"
512 /*@
513     PetscViewerDrawGetPause - Gets a pause for the first present draw
514 
515     Not Collective
516 
517     Input Parameter:
518 .  viewer - the PetscViewer
519 
520     Output Parameter:
521 .  pause - the pause value
522 
523     Level: intermediate
524 
525 .seealso: PetscViewerDrawOpen(), PetscViewerDrawGetDraw(),
526 
527 @*/
528 PetscErrorCode  PetscViewerDrawGetPause(PetscViewer viewer,PetscReal *pause)
529 {
530   PetscErrorCode   ierr;
531   PetscInt         i;
532   PetscBool        isdraw;
533   PetscViewer_Draw *vdraw;
534   PetscDraw        draw;
535 
536   PetscFunctionBegin;
537   ierr   = PetscObjectTypeCompare((PetscObject)viewer,PETSCVIEWERDRAW,&isdraw);CHKERRQ(ierr);
538   *pause = 0.0;
539   if (isdraw) {
540     vdraw = (PetscViewer_Draw*)viewer->data;
541     for (i=0; i<vdraw->draw_max; i++) {
542       if (vdraw->draw[i]) {
543         ierr = PetscDrawGetPause(vdraw->draw[i],pause);CHKERRQ(ierr);
544         PetscFunctionReturn(0);
545       }
546     }
547     /* none exist yet so create one and get its pause */
548     ierr = PetscViewerDrawGetDraw(viewer,0,&draw);CHKERRQ(ierr);
549     ierr = PetscDrawGetPause(vdraw->draw[0],pause);CHKERRQ(ierr);
550   }
551   PetscFunctionReturn(0);
552 }
553 
554 #undef __FUNCT__
555 #define __FUNCT__ "PetscViewerDrawSetPause"
556 /*@
557     PetscViewerDrawSetPause - Sets a pause for each PetscDraw in the viewer
558 
559     Not Collective
560 
561     Input Parameters:
562 +  viewer - the PetscViewer
563 -  pause - the pause value
564 
565     Level: intermediate
566 
567 .seealso: PetscViewerDrawOpen(), PetscViewerDrawGetDraw(),
568 
569 @*/
570 PetscErrorCode  PetscViewerDrawSetPause(PetscViewer viewer,PetscReal pause)
571 {
572   PetscErrorCode   ierr;
573   PetscInt         i;
574   PetscBool        isdraw;
575 
576   PetscFunctionBegin;
577   ierr = PetscObjectTypeCompare((PetscObject)viewer,PETSCVIEWERDRAW,&isdraw);CHKERRQ(ierr);
578   if (isdraw) {
579     PetscViewer_Draw *vdraw = (PetscViewer_Draw*)viewer->data;
580 
581     vdraw->pause = pause;
582     for (i=0; i<vdraw->draw_max; i++) {
583       if (vdraw->draw[i]) {ierr = PetscDrawSetPause(vdraw->draw[i],pause);CHKERRQ(ierr);}
584     }
585   }
586   PetscFunctionReturn(0);
587 }
588 
589 
590 #undef __FUNCT__
591 #define __FUNCT__ "PetscViewerDrawSetHold"
592 /*@
593     PetscViewerDrawSetHold - Holds previous image when drawing new image
594 
595     Not Collective
596 
597     Input Parameters:
598 +  viewer - the PetscViewer
599 -  hold - indicates to hold or not
600 
601     Level: intermediate
602 
603 .seealso: PetscViewerDrawOpen(), PetscViewerDrawGetDraw(),
604 
605 @*/
606 PetscErrorCode  PetscViewerDrawSetHold(PetscViewer viewer,PetscBool hold)
607 {
608   PetscErrorCode   ierr;
609   PetscViewer_Draw *vdraw;
610   PetscBool        isdraw;
611 
612   PetscFunctionBegin;
613   ierr = PetscObjectTypeCompare((PetscObject)viewer,PETSCVIEWERDRAW,&isdraw);CHKERRQ(ierr);
614   if (isdraw) {
615     vdraw       = (PetscViewer_Draw*)viewer->data;
616     vdraw->hold = hold;
617   }
618   PetscFunctionReturn(0);
619 }
620 
621 #undef __FUNCT__
622 #define __FUNCT__ "PetscViewerDrawGetHold"
623 /*@
624     PetscViewerDrawGetHold - Holds previous image when drawing new image
625 
626     Not Collective
627 
628     Input Parameter:
629 .  viewer - the PetscViewer
630 
631     Output Parameter:
632 .  hold - indicates to hold or not
633 
634     Level: intermediate
635 
636 .seealso: PetscViewerDrawOpen(), PetscViewerDrawGetDraw(),
637 
638 @*/
639 PetscErrorCode  PetscViewerDrawGetHold(PetscViewer viewer,PetscBool *hold)
640 {
641   PetscErrorCode   ierr;
642   PetscViewer_Draw *vdraw;
643   PetscBool        isdraw;
644 
645   PetscFunctionBegin;
646   ierr = PetscObjectTypeCompare((PetscObject)viewer,PETSCVIEWERDRAW,&isdraw);CHKERRQ(ierr);
647   if (isdraw) {
648     vdraw = (PetscViewer_Draw*)viewer->data;
649     *hold = vdraw->hold;
650   }
651   PetscFunctionReturn(0);
652 }
653 
654 /* ---------------------------------------------------------------------*/
655 /*
656     The variable Petsc_Viewer_Draw_keyval is used to indicate an MPI attribute that
657   is attached to a communicator, in this case the attribute is a PetscViewer.
658 */
659 static PetscMPIInt Petsc_Viewer_Draw_keyval = MPI_KEYVAL_INVALID;
660 
661 #undef __FUNCT__
662 #define __FUNCT__ "PETSC_VIEWER_DRAW_"
663 /*@C
664     PETSC_VIEWER_DRAW_ - Creates a window PetscViewer shared by all processors
665                      in a communicator.
666 
667      Collective on MPI_Comm
668 
669      Input Parameter:
670 .    comm - the MPI communicator to share the window PetscViewer
671 
672      Level: intermediate
673 
674      Notes:
675      Unlike almost all other PETSc routines, PETSC_VIEWER_DRAW_ does not return
676      an error code.  The window is usually used in the form
677 $       XXXView(XXX object,PETSC_VIEWER_DRAW_(comm));
678 
679 .seealso: PETSC_VIEWER_DRAW_WORLD, PETSC_VIEWER_DRAW_SELF, PetscViewerDrawOpen(),
680 @*/
681 PetscViewer  PETSC_VIEWER_DRAW_(MPI_Comm comm)
682 {
683   PetscErrorCode ierr;
684   PetscMPIInt    flag;
685   PetscViewer    viewer;
686   MPI_Comm       ncomm;
687 
688   PetscFunctionBegin;
689   ierr = PetscCommDuplicate(comm,&ncomm,NULL);if (ierr) {PetscError(PETSC_COMM_SELF,__LINE__,"PETSC_VIEWER_DRAW_",__FILE__,__SDIR__,PETSC_ERR_PLIB,PETSC_ERROR_INITIAL," ");PetscFunctionReturn(0);}
690   if (Petsc_Viewer_Draw_keyval == MPI_KEYVAL_INVALID) {
691     ierr = MPI_Keyval_create(MPI_NULL_COPY_FN,MPI_NULL_DELETE_FN,&Petsc_Viewer_Draw_keyval,0);
692     if (ierr) {PetscError(PETSC_COMM_SELF,__LINE__,"PETSC_VIEWER_DRAW_",__FILE__,__SDIR__,PETSC_ERR_PLIB,PETSC_ERROR_INITIAL," ");PetscFunctionReturn(0);}
693   }
694   ierr = MPI_Attr_get(ncomm,Petsc_Viewer_Draw_keyval,(void**)&viewer,&flag);
695   if (ierr) {PetscError(PETSC_COMM_SELF,__LINE__,"PETSC_VIEWER_DRAW_",__FILE__,__SDIR__,PETSC_ERR_PLIB,PETSC_ERROR_INITIAL," ");PetscFunctionReturn(0);}
696   if (!flag) { /* PetscViewer not yet created */
697     ierr = PetscViewerDrawOpen(ncomm,0,0,PETSC_DECIDE,PETSC_DECIDE,300,300,&viewer);
698     if (ierr) {PetscError(PETSC_COMM_SELF,__LINE__,"PETSC_VIEWER_DRAW_",__FILE__,__SDIR__,PETSC_ERR_PLIB,PETSC_ERROR_INITIAL," ");PetscFunctionReturn(0);}
699     ierr = PetscObjectRegisterDestroy((PetscObject)viewer);
700     if (ierr) {PetscError(PETSC_COMM_SELF,__LINE__,"PETSC_VIEWER_DRAW_",__FILE__,__SDIR__,PETSC_ERR_PLIB,PETSC_ERROR_INITIAL," ");PetscFunctionReturn(0);}
701     ierr = MPI_Attr_put(ncomm,Petsc_Viewer_Draw_keyval,(void*)viewer);
702     if (ierr) {PetscError(PETSC_COMM_SELF,__LINE__,"PETSC_VIEWER_DRAW_",__FILE__,__SDIR__,PETSC_ERR_PLIB,PETSC_ERROR_INITIAL," ");PetscFunctionReturn(0);}
703   }
704   ierr = PetscCommDestroy(&ncomm);
705   if (ierr) {PetscError(PETSC_COMM_SELF,__LINE__,"PETSC_VIEWER_DRAW_",__FILE__,__SDIR__,PETSC_ERR_PLIB,PETSC_ERROR_INITIAL," ");PetscFunctionReturn(0);}
706   PetscFunctionReturn(viewer);
707 }
708 
709 #undef __FUNCT__
710 #define __FUNCT__ "PetscViewerDrawSetBounds"
711 /*@
712     PetscViewerDrawSetBounds - sets the upper and lower bounds to be used in plotting
713 
714     Collective on PetscViewer
715 
716     Input Parameters:
717 +   viewer - the PetscViewer (created with PetscViewerDrawOpen())
718 .   nbounds - number of plots that can be made with this viewer, for example the dof passed to DMDACreate()
719 -   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, .....
720 
721 
722     Options Database:
723 .   -draw_bounds  minF0,maxF0,minF1,maxF1
724 
725     Level: intermediate
726 
727     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
728       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
729       this viewer. Otherwise the color to physical value meaning changes with each new image if this is not set.
730 
731    Concepts: drawing^accessing PetscDraw context from PetscViewer
732    Concepts: graphics
733 
734 .seealso: PetscViewerDrawGetLG(), PetscViewerDrawGetAxis(), PetscViewerDrawOpen()
735 @*/
736 PetscErrorCode  PetscViewerDrawSetBounds(PetscViewer viewer,PetscInt nbounds,const PetscReal *bounds)
737 {
738   PetscViewer_Draw *vdraw = (PetscViewer_Draw*)viewer->data;
739   PetscErrorCode   ierr;
740 
741 
742   PetscFunctionBegin;
743   PetscValidHeaderSpecific(viewer,PETSC_VIEWER_CLASSID,1);
744   vdraw->nbounds = nbounds;
745 
746   ierr = PetscMalloc(2*nbounds*sizeof(PetscReal),&vdraw->bounds);CHKERRQ(ierr);
747   ierr = PetscMemcpy(vdraw->bounds,bounds,2*nbounds*sizeof(PetscReal));CHKERRQ(ierr);
748   PetscFunctionReturn(0);
749 }
750 
751 #undef __FUNCT__
752 #define __FUNCT__ "PetscViewerDrawGetBounds"
753 /*@C
754     PetscViewerDrawGetBounds - gets the upper and lower bounds to be used in plotting set with PetscViewerDrawSetBounds()
755 
756     Collective on PetscViewer
757 
758     Input Parameter:
759 .   viewer - the PetscViewer (created with PetscViewerDrawOpen())
760 
761     Output Paramters:
762 +   nbounds - number of plots that can be made with this viewer, for example the dof passed to DMDACreate()
763 -   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, .....
764 
765     Level: intermediate
766 
767    Concepts: drawing^accessing PetscDraw context from PetscViewer
768    Concepts: graphics
769 
770 .seealso: PetscViewerDrawGetLG(), PetscViewerDrawGetAxis(), PetscViewerDrawOpen(), PetscViewerDrawSetBounds()
771 @*/
772 PetscErrorCode  PetscViewerDrawGetBounds(PetscViewer viewer,PetscInt *nbounds,const PetscReal **bounds)
773 {
774   PetscViewer_Draw *vdraw = (PetscViewer_Draw*)viewer->data;
775 
776   PetscFunctionBegin;
777   PetscValidHeaderSpecific(viewer,PETSC_VIEWER_CLASSID,1);
778   *nbounds = vdraw->nbounds;
779   *bounds  = vdraw->bounds;
780   PetscFunctionReturn(0);
781 }
782