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