xref: /petsc/src/sys/classes/draw/interface/drawreg.c (revision e6e75211d226c622f451867f53ce5d558649ff4f)
1 
2 /*
3        Provides the registration process for PETSc PetscDraw routines
4 */
5 #include <petsc/private/drawimpl.h>  /*I "petscdraw.h" I*/
6 #include <petscviewer.h>             /*I "petscviewer.h" I*/
7 #if defined(PETSC_HAVE_SAWS)
8 #include <petscviewersaws.h>
9 #endif
10 
11 /*
12    Contains the list of registered PetscDraw routines
13 */
14 PetscFunctionList PetscDrawList = 0;
15 
16 #undef __FUNCT__
17 #define __FUNCT__ "PetscDrawView"
18 /*@C
19    PetscDrawView - Prints the PetscDraw data structure.
20 
21    Collective on PetscDraw
22 
23    Input Parameters:
24 +  indraw - the PetscDraw context
25 -  viewer - visualization context
26 
27    See PetscDrawSetFromOptions() for options database keys
28 
29    Note:
30    The available visualization contexts include
31 +     PETSC_VIEWER_STDOUT_SELF - standard output (default)
32 -     PETSC_VIEWER_STDOUT_WORLD - synchronized standard
33          output where only the first processor opens
34          the file.  All other processors send their
35          data to the first processor to print.
36 
37    The user can open an alternative visualization context with
38    PetscViewerASCIIOpen() - output to a specified file.
39 
40    Level: beginner
41 
42 .keywords: PetscDraw, view
43 
44 .seealso: PCView(), PetscViewerASCIIOpen()
45 @*/
46 PetscErrorCode  PetscDrawView(PetscDraw indraw,PetscViewer viewer)
47 {
48   PetscErrorCode ierr;
49   PetscBool      isdraw;
50 #if defined(PETSC_HAVE_SAWS)
51   PetscBool      issaws;
52 #endif
53 
54   PetscFunctionBegin;
55   PetscValidHeaderSpecific(indraw,PETSC_DRAW_CLASSID,1);
56   if (!viewer) viewer = PETSC_VIEWER_STDOUT_(PetscObjectComm((PetscObject)indraw));
57   PetscValidHeaderSpecific(viewer,PETSC_VIEWER_CLASSID,2);
58   PetscCheckSameComm(indraw,1,viewer,2);
59 
60   ierr = PetscObjectPrintClassNamePrefixType((PetscObject)indraw,viewer);CHKERRQ(ierr);
61   ierr = PetscObjectTypeCompare((PetscObject)viewer,PETSCVIEWERDRAW,&isdraw);CHKERRQ(ierr);
62 #if defined(PETSC_HAVE_SAWS)
63   ierr = PetscObjectTypeCompare((PetscObject)viewer,PETSCVIEWERSAWS,&issaws);CHKERRQ(ierr);
64 #endif
65   if (isdraw) {
66     PetscDraw draw;
67     char      str[36];
68     PetscReal x,y,bottom,h;
69 
70     ierr = PetscViewerDrawGetDraw(viewer,0,&draw);CHKERRQ(ierr);
71     ierr = PetscDrawGetCurrentPoint(draw,&x,&y);CHKERRQ(ierr);
72     ierr   = PetscStrcpy(str,"PetscDraw: ");CHKERRQ(ierr);
73     ierr   = PetscStrcat(str,((PetscObject)indraw)->type_name);CHKERRQ(ierr);
74     ierr   = PetscDrawStringBoxed(draw,x,y,PETSC_DRAW_RED,PETSC_DRAW_BLACK,str,NULL,&h);CHKERRQ(ierr);
75     bottom = y - h;
76     ierr = PetscDrawPushCurrentPoint(draw,x,bottom);CHKERRQ(ierr);
77 #if defined(PETSC_HAVE_SAWS)
78   } else if (issaws) {
79     PetscMPIInt rank;
80 
81     ierr = PetscObjectName((PetscObject)indraw);CHKERRQ(ierr);
82     ierr = MPI_Comm_rank(PETSC_COMM_WORLD,&rank);CHKERRQ(ierr);
83     if (!((PetscObject)indraw)->amsmem && !rank) {
84       ierr = PetscObjectViewSAWs((PetscObject)indraw,viewer);CHKERRQ(ierr);
85     }
86 #endif
87   } else if (indraw->ops->view) {
88     ierr = (*indraw->ops->view)(indraw,viewer);CHKERRQ(ierr);
89   }
90   PetscFunctionReturn(0);
91 }
92 
93 #undef __FUNCT__
94 #define __FUNCT__ "PetscDrawCreate"
95 /*@C
96    PetscDrawCreate - Creates a graphics context.
97 
98    Collective on MPI_Comm
99 
100    Input Parameter:
101 +  comm - MPI communicator
102 .  display - X display when using X windows
103 .  title - optional title added to top of window
104 .  x,y - coordinates of lower left corner of window or PETSC_DECIDE
105 -  w, h - width and height of window or PETSC_DECIDE or PETSC_DRAW_HALF_SIZE, PETSC_DRAW_FULL_SIZE,
106           or PETSC_DRAW_THIRD_SIZE or PETSC_DRAW_QUARTER_SIZE
107 
108    Output Parameter:
109 .  draw - location to put the PetscDraw context
110 
111    Level: beginner
112 
113    Concepts: graphics^creating context
114    Concepts: drawing^creating context
115 
116 .seealso: PetscDrawSetFromOptions(), PetscDrawDestroy(), PetscDrawSetType()
117 @*/
118 PetscErrorCode  PetscDrawCreate(MPI_Comm comm,const char display[],const char title[],int x,int y,int w,int h,PetscDraw *indraw)
119 {
120   PetscDraw      draw;
121   PetscErrorCode ierr;
122   PetscReal      dpause;
123   PetscBool      flag;
124 
125   PetscFunctionBegin;
126   ierr = PetscDrawInitializePackage();CHKERRQ(ierr);
127   *indraw = 0;
128   ierr = PetscHeaderCreate(draw,PETSC_DRAW_CLASSID,"Draw","Graphics","Draw",comm,PetscDrawDestroy,PetscDrawView);CHKERRQ(ierr);
129 
130   draw->data    = 0;
131   ierr          = PetscStrallocpy(title,&draw->title);CHKERRQ(ierr);
132   ierr          = PetscStrallocpy(display,&draw->display);CHKERRQ(ierr);
133   draw->x       = x;
134   draw->y       = y;
135   draw->w       = w;
136   draw->h       = h;
137   draw->pause   = 0.0;
138   draw->coor_xl = 0.0;
139   draw->coor_xr = 1.0;
140   draw->coor_yl = 0.0;
141   draw->coor_yr = 1.0;
142   draw->port_xl = 0.0;
143   draw->port_xr = 1.0;
144   draw->port_yl = 0.0;
145   draw->port_yr = 1.0;
146   draw->popup   = 0;
147 
148   ierr = PetscOptionsGetReal(NULL,"-draw_pause",&dpause,&flag);CHKERRQ(ierr);
149   if (flag) draw->pause = dpause;
150   draw->savefilename  = NULL;
151   draw->savefilemovie = PETSC_FALSE;
152   draw->savefilecount = -1;
153 
154   ierr = PetscDrawSetCurrentPoint(draw,.5,.9);CHKERRQ(ierr);
155 
156   draw->boundbox_xl  = .5;
157   draw->boundbox_xr  = .5;
158   draw->boundbox_yl  = .9;
159   draw->boundbox_yr  = .9;
160 
161   *indraw = draw;
162   PetscFunctionReturn(0);
163 }
164 
165 #undef __FUNCT__
166 #define __FUNCT__ "PetscDrawSetType"
167 /*@C
168    PetscDrawSetType - Builds graphics object for a particular implementation
169 
170    Collective on PetscDraw
171 
172    Input Parameter:
173 +  draw      - the graphics context
174 -  type      - for example, PETSC_DRAW_X
175 
176    Options Database Command:
177 .  -draw_type  <type> - Sets the type; use -help for a list of available methods (for instance, x)
178 
179    See PetscDrawSetFromOptions for additional options database keys
180 
181    Level: intermediate
182 
183    Notes:
184    See "petsc/include/petscdraw.h" for available methods (for instance,
185    PETSC_DRAW_X)
186 
187    Concepts: drawing^X windows
188    Concepts: X windows^graphics
189    Concepts: drawing^Microsoft Windows
190 
191 .seealso: PetscDrawSetFromOptions(), PetscDrawCreate(), PetscDrawDestroy()
192 @*/
193 PetscErrorCode  PetscDrawSetType(PetscDraw draw,PetscDrawType type)
194 {
195   PetscErrorCode ierr,(*r)(PetscDraw);
196   PetscBool      match;
197   PetscBool      flg=PETSC_FALSE;
198 
199   PetscFunctionBegin;
200   PetscValidHeaderSpecific(draw,PETSC_DRAW_CLASSID,1);
201   PetscValidCharPointer(type,2);
202 
203   ierr = PetscObjectTypeCompare((PetscObject)draw,type,&match);CHKERRQ(ierr);
204   if (match) PetscFunctionReturn(0);
205 
206   /*  User requests no graphics */
207   ierr = PetscOptionsHasName(NULL,"-nox",&flg);CHKERRQ(ierr);
208 
209   /*
210      This is not ideal, but it allows codes to continue to run if X graphics
211    was requested but is not installed on this machine. Mostly this is for
212    testing.
213    */
214 #if !defined(PETSC_HAVE_X)
215   if (!flg) {
216     ierr = PetscStrcmp(type,PETSC_DRAW_X,&match);CHKERRQ(ierr);
217     if (match) {
218       PetscBool dontwarn = PETSC_TRUE;
219       flg  = PETSC_TRUE;
220       ierr = PetscOptionsHasName(NULL,"-nox_warning",&dontwarn);CHKERRQ(ierr);
221       if (!dontwarn) (*PetscErrorPrintf)("PETSc installed without X windows on this machine\nproceeding without graphics\n");
222     }
223   }
224 #endif
225   if (flg) type = PETSC_DRAW_NULL;
226 
227   ierr =  PetscFunctionListFind(PetscDrawList,type,&r);CHKERRQ(ierr);
228   if (!r) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_ARG_UNKNOWN_TYPE,"Unknown PetscDraw type given: %s",type);
229   if (draw->ops->destroy) {ierr = (*draw->ops->destroy)(draw);CHKERRQ(ierr);}
230   ierr = PetscMemzero(draw->ops,sizeof(struct _PetscDrawOps));CHKERRQ(ierr);
231   ierr       = PetscObjectChangeTypeName((PetscObject)draw,type);CHKERRQ(ierr);
232   ierr       = (*r)(draw);CHKERRQ(ierr);
233   PetscFunctionReturn(0);
234 }
235 
236 #undef __FUNCT__
237 #define __FUNCT__ "PetscDrawGetType"
238 /*@C
239    PetscDrawGetType - Gets the PetscDraw type as a string from the PetscDraw object.
240 
241    Not Collective
242 
243    Input Parameter:
244 .  draw - Krylov context
245 
246    Output Parameters:
247 .  name - name of PetscDraw method
248 
249    Level: advanced
250 
251 @*/
252 PetscErrorCode  PetscDrawGetType(PetscDraw draw,PetscDrawType *type)
253 {
254   PetscFunctionBegin;
255   PetscValidHeaderSpecific(draw,PETSC_DRAW_CLASSID,1);
256   PetscValidPointer(type,2);
257   *type = ((PetscObject)draw)->type_name;
258   PetscFunctionReturn(0);
259 }
260 
261 #undef __FUNCT__
262 #define __FUNCT__ "PetscDrawRegister"
263 /*@C
264    PetscDrawRegister - Adds a method to the graphics package.
265 
266    Not Collective
267 
268    Input Parameters:
269 +  name_solver - name of a new user-defined graphics class
270 -  routine_create - routine to create method context
271 
272    Level: developer
273 
274    Notes:
275    PetscDrawRegister() may be called multiple times to add several user-defined graphics classes
276 
277    Sample usage:
278 .vb
279    PetscDrawRegister("my_draw_type", MyDrawCreate);
280 .ve
281 
282    Then, your specific graphics package can be chosen with the procedural interface via
283 $     PetscDrawSetType(ksp,"my_draw_type")
284    or at runtime via the option
285 $     -draw_type my_draw_type
286 
287    Concepts: graphics^registering new draw classes
288    Concepts: PetscDraw^registering new draw classes
289 
290 .seealso: PetscDrawRegisterAll(), PetscDrawRegisterDestroy()
291 @*/
292 PetscErrorCode  PetscDrawRegister(const char *sname,PetscErrorCode (*function)(PetscDraw))
293 {
294   PetscErrorCode ierr;
295 
296   PetscFunctionBegin;
297   ierr = PetscFunctionListAdd(&PetscDrawList,sname,function);CHKERRQ(ierr);
298   PetscFunctionReturn(0);
299 }
300 
301 #undef __FUNCT__
302 #define __FUNCT__ "PetscDrawSetFromOptions"
303 /*@
304    PetscDrawSetFromOptions - Sets the graphics type from the options database.
305       Defaults to a PETSc X windows graphics.
306 
307    Collective on PetscDraw
308 
309    Input Parameter:
310 .     draw - the graphics context
311 
312    Options Database Keys:
313 +   -nox - do not use X graphics (ignore graphics calls, but run program correctly)
314 .   -nox_warning - when X windows support is not installed this prevents the warning message from being printed
315 .   -draw_pause <pause amount> -- -1 indicates wait for mouse input, -2 indicates pause when window is to be destroyed
316 .   -draw_marker_type - <x,point>
317 .   -draw_save [optional filename] - (X windows only) saves each image before it is cleared to a file
318 .   -draw_save_final_image [optional filename] - (X windows only) saves the final image displayed in a window
319 .   -draw_save_movie - converts image files to a movie  at the end of the run. See PetscDrawSetSave()
320 .   -draw_save_on_flush - saves an image on each flush in addition to each clear
321 -   -draw_save_single_file - saves each new image in the same file, normally each new image is saved in a new file with filename_%d
322 
323    Level: intermediate
324 
325    Notes:
326     Must be called after PetscDrawCreate() before the PetscDraw is used.
327 
328     Concepts: drawing^setting options
329     Concepts: graphics^setting options
330 
331 .seealso: PetscDrawCreate(), PetscDrawSetType(), PetscDrawSetSave(), PetscDrawSetSaveFinalImage()
332 
333 @*/
334 PetscErrorCode  PetscDrawSetFromOptions(PetscDraw draw)
335 {
336   PetscErrorCode    ierr;
337   PetscBool         flg,nox;
338   char              vtype[256];
339   const char        *def;
340   PetscReal         dpause;
341 #if !defined(PETSC_USE_WINDOWS_GRAPHICS) && !defined(PETSC_HAVE_X)
342   PetscBool         warn;
343 #endif
344 
345   PetscFunctionBegin;
346   PetscValidHeaderSpecific(draw,PETSC_DRAW_CLASSID,1);
347 
348   if (!PetscDrawList) {
349     ierr = PetscDrawRegisterAll();CHKERRQ(ierr);
350   }
351 
352   if (((PetscObject)draw)->type_name) def = ((PetscObject)draw)->type_name;
353   else {
354     ierr = PetscOptionsHasName(NULL,"-nox",&nox);CHKERRQ(ierr);
355     def  = PETSC_DRAW_NULL;
356 #if defined(PETSC_USE_WINDOWS_GRAPHICS)
357     if (!nox) def = PETSC_DRAW_WIN32;
358 #elif defined(PETSC_HAVE_X)
359     if (!nox) def = PETSC_DRAW_X;
360 #elif defined(PETSC_HAVE_GLUT)
361     if (!nox) def = PETSC_DRAW_GLUT;
362 #elif defined(PETSC_HAVE_OPENGLES)
363     if (!nox) def = PETSC_DRAW_OPENGLES;
364 #else
365     ierr = PetscOptionsHasName(NULL,"-nox_warning",&warn);CHKERRQ(ierr);
366     if (!nox && !warn) (*PetscErrorPrintf)("PETSc installed without X windows, Microsoft Graphics, OpenGL ES, or GLUT/OpenGL on this machine\nproceeding without graphics\n");
367 #endif
368   }
369   ierr = PetscObjectOptionsBegin((PetscObject)draw);CHKERRQ(ierr);
370   ierr = PetscOptionsFList("-draw_type","Type of graphical output","PetscDrawSetType",PetscDrawList,def,vtype,256,&flg);CHKERRQ(ierr);
371   if (flg) {
372     ierr = PetscDrawSetType(draw,vtype);CHKERRQ(ierr);
373   } else if (!((PetscObject)draw)->type_name) {
374     ierr = PetscDrawSetType(draw,def);CHKERRQ(ierr);
375   }
376   ierr = PetscOptionsName("-nox","Run without graphics","None",&nox);CHKERRQ(ierr);
377 #if defined(PETSC_HAVE_X)
378   {
379     char      filename[PETSC_MAX_PATH_LEN];
380     PetscBool save,movie = PETSC_FALSE;
381     ierr = PetscOptionsBool("-draw_save_movie","Make a movie from the images saved (X Windows only)","PetscDrawSetSave",movie,&movie,NULL);CHKERRQ(ierr);
382     ierr = PetscOptionsBool("-draw_save_single_file","Each new image replaces previous image in file","PetscDrawSetSave",draw->savesinglefile,&draw->savesinglefile,NULL);CHKERRQ(ierr);
383     ierr = PetscOptionsString("-draw_save","Save graphics to file (X Windows only)","PetscDrawSetSave",filename,filename,PETSC_MAX_PATH_LEN,&save);CHKERRQ(ierr);
384     if (save) {
385       ierr = PetscDrawSetSave(draw,filename,movie);CHKERRQ(ierr);
386     }
387     ierr = PetscOptionsString("-draw_save_final_image","Save graphics to file (X Windows only)","PetscDrawSetSaveFinalImage",filename,filename,PETSC_MAX_PATH_LEN,&save);CHKERRQ(ierr);
388     if (save) {
389       ierr = PetscDrawSetSaveFinalImage(draw,filename);CHKERRQ(ierr);
390     }
391     ierr = PetscOptionsBool("-draw_save_on_flush","Save graphics to file (X Windows only) on each flush","PetscDrawSetSave",draw->saveonflush,&draw->saveonflush,NULL);CHKERRQ(ierr);
392   }
393 #endif
394   ierr = PetscOptionsGetReal(NULL,"-draw_pause",&dpause,&flg);CHKERRQ(ierr);
395   if (flg) draw->pause = dpause;
396 
397   ierr = PetscOptionsEnum("-draw_marker_type","Type of marker to use on plots","PetscDrawSetMarkerType",PetscDrawMarkerTypes,(PetscEnum)draw->markertype,(PetscEnum *)&draw->markertype,NULL);CHKERRQ(ierr);
398 
399   /* process any options handlers added with PetscObjectAddOptionsHandler() */
400   ierr = PetscObjectProcessOptionsHandlers((PetscObject)draw);CHKERRQ(ierr);
401 
402   ierr = PetscDrawViewFromOptions(draw,NULL,"-draw_view");CHKERRQ(ierr);
403   ierr = PetscOptionsEnd();CHKERRQ(ierr);
404   PetscFunctionReturn(0);
405 }
406 
407 #undef __FUNCT__
408 #define __FUNCT__ "PetscDrawSetSave"
409 /*@C
410    PetscDrawSetSave - Saves images produced in a PetscDraw into a file as a Gif file using AfterImage
411 
412    Collective on PetscDraw
413 
414    Input Parameter:
415 +  draw      - the graphics context
416 .  filename  - name of the file, if .ext then uses name of draw object plus .ext using .ext to determine the image type, if NULL use .Gif image type
417 -  movie - produce a movie of all the images
418 
419    Options Database Command:
420 +  -draw_save  <filename> - filename could be name.ext or .ext (where .ext determines the type of graphics file to save, for example .Gif)
421 .  -draw_save_movie
422 .  -draw_save_final_image [optional filename] - (X windows only) saves the final image displayed in a window
423 .  -draw_save_on_flush - saves an image on each flush in addition to each clear
424 -  -draw_save_single_file - saves each new image in the same file, normally each new image is saved in a new file with filename_%d
425 
426    Level: intermediate
427 
428    Concepts: X windows^graphics
429 
430    Notes: You should call this BEFORE calling PetscDrawClear() and creating your image.
431 
432    Requires that PETSc be configured with the option --with-afterimage to save the images and ffmpeg must be in your path to make the movie
433 
434    The .ext formats that are supported depend on what formats AfterImage was configured with; on the Apple Mac both .Gif and .Jpeg are supported.
435 
436    If X windows generates an error message about X_CreateWindow() failing then Afterimage was installed without X windows. Reinstall Afterimage using the
437    ./configure flags --x-includes=/pathtoXincludes --x-libraries=/pathtoXlibraries   For example under Mac OS X Mountain Lion --x-includes=/opt/X11/include -x-libraries=/opt/X11/lib
438 
439 
440 .seealso: PetscDrawSetFromOptions(), PetscDrawCreate(), PetscDrawDestroy(), PetscDrawSetSaveFinalImage()
441 @*/
442 PetscErrorCode  PetscDrawSetSave(PetscDraw draw,const char *filename,PetscBool movie)
443 {
444   PetscErrorCode ierr;
445   char           *ext;
446 
447   PetscFunctionBegin;
448   PetscValidHeaderSpecific(draw,PETSC_DRAW_CLASSID,1);
449   ierr = PetscFree(draw->savefilename);CHKERRQ(ierr);
450 
451   /* determine extension of filename */
452   if (filename && filename[0]) {
453     ierr = PetscStrchr(filename,'.',&ext);CHKERRQ(ierr);
454     if (!ext) SETERRQ1(PetscObjectComm((PetscObject)draw),PETSC_ERR_ARG_INCOMP,"Filename %s should end with graphics extension (for example .Gif)",filename);
455   } else {
456     ext = (char *)".Gif";
457   }
458   if (ext == filename) filename = NULL;
459   ierr = PetscStrallocpy(ext,&draw->savefilenameext);CHKERRQ(ierr);
460 
461   draw->savefilemovie = movie;
462   if (filename && filename[0]) {
463     size_t  l1,l2;
464     ierr = PetscStrlen(filename,&l1);CHKERRQ(ierr);
465     ierr = PetscStrlen(ext,&l2);CHKERRQ(ierr);
466     ierr = PetscMalloc1(l1-l2+1,&draw->savefilename);CHKERRQ(ierr);
467     ierr = PetscStrncpy(draw->savefilename,filename,l1-l2+1);CHKERRQ(ierr);
468   } else {
469     const char *name;
470 
471     ierr = PetscObjectGetName((PetscObject)draw,&name);CHKERRQ(ierr);
472     ierr = PetscStrallocpy(name,&draw->savefilename);CHKERRQ(ierr);
473   }
474   ierr = PetscInfo2(NULL,"Will save images to file %s%s\n",draw->savefilename,draw->savefilenameext);CHKERRQ(ierr);
475   if (draw->ops->setsave) {
476     ierr = (*draw->ops->setsave)(draw,draw->savefilename);CHKERRQ(ierr);
477   }
478   PetscFunctionReturn(0);
479 }
480 
481 #undef __FUNCT__
482 #define __FUNCT__ "PetscDrawSetSaveFinalImage"
483 /*@C
484    PetscDrawSetSaveFinalImage - Saves the finale image produced in a PetscDraw into a file as a Gif file using AfterImage
485 
486    Collective on PetscDraw
487 
488    Input Parameter:
489 +  draw      - the graphics context
490 -  filename  - name of the file, if NULL uses name of draw object
491 
492    Options Database Command:
493 .  -draw_save_final_image  <filename>
494 
495    Level: intermediate
496 
497    Concepts: X windows^graphics
498 
499    Notes: You should call this BEFORE calling PetscDrawClear() and creating your image.
500 
501    Requires that PETSc be configured with the option --with-afterimage to save the images and ffmpeg must be in your path to make the movie
502 
503    If X windows generates an error message about X_CreateWindow() failing then Afterimage was installed without X windows. Reinstall Afterimage using the
504    ./configure flags --x-includes=/pathtoXincludes --x-libraries=/pathtoXlibraries   For example under Mac OS X Mountain Lion --x-includes=/opt/X11/include -x-libraries=/opt/X11/lib
505 
506 
507 .seealso: PetscDrawSetFromOptions(), PetscDrawCreate(), PetscDrawDestroy(), PetscDrawSetSave()
508 @*/
509 PetscErrorCode  PetscDrawSetSaveFinalImage(PetscDraw draw,const char *filename)
510 {
511   PetscErrorCode ierr;
512 
513   PetscFunctionBegin;
514   PetscValidHeaderSpecific(draw,PETSC_DRAW_CLASSID,1);
515   ierr = PetscFree(draw->savefinalfilename);CHKERRQ(ierr);
516 
517   if (filename && filename[0]) {
518     ierr = PetscStrallocpy(filename,&draw->savefinalfilename);CHKERRQ(ierr);
519   } else {
520     const char *name;
521     ierr = PetscObjectGetName((PetscObject)draw,&name);CHKERRQ(ierr);
522     ierr = PetscStrallocpy(name,&draw->savefinalfilename);CHKERRQ(ierr);
523   }
524   PetscFunctionReturn(0);
525 }
526