xref: /petsc/src/sys/classes/draw/interface/drawreg.c (revision f97672e55eacc8688507b9471cd7ec2664d7f203)
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 = NULL;
15 
16 /*@C
17    PetscDrawView - Prints the PetscDraw data structure.
18 
19    Collective on PetscDraw
20 
21    Input Parameters:
22 +  indraw - the PetscDraw context
23 -  viewer - visualization context
24 
25    See PetscDrawSetFromOptions() for options database keys
26 
27    Note:
28    The available visualization contexts include
29 +     PETSC_VIEWER_STDOUT_SELF - standard output (default)
30 -     PETSC_VIEWER_STDOUT_WORLD - synchronized standard
31          output where only the first processor opens
32          the file.  All other processors send their
33          data to the first processor to print.
34 
35    The user can open an alternative visualization context with
36    PetscViewerASCIIOpen() - output to a specified file.
37 
38    Level: beginner
39 
40 .seealso: `PCView()`, `PetscViewerASCIIOpen()`
41 @*/
42 PetscErrorCode  PetscDrawView(PetscDraw indraw,PetscViewer viewer)
43 {
44   PetscBool      isdraw;
45 #if defined(PETSC_HAVE_SAWS)
46   PetscBool      issaws;
47 #endif
48 
49   PetscFunctionBegin;
50   PetscValidHeaderSpecific(indraw,PETSC_DRAW_CLASSID,1);
51   if (!viewer) {
52     PetscCall(PetscViewerASCIIGetStdout(PetscObjectComm((PetscObject)indraw),&viewer));
53   }
54   PetscValidHeaderSpecific(viewer,PETSC_VIEWER_CLASSID,2);
55   PetscCheckSameComm(indraw,1,viewer,2);
56 
57   PetscCall(PetscObjectPrintClassNamePrefixType((PetscObject)indraw,viewer));
58   PetscCall(PetscObjectTypeCompare((PetscObject)viewer,PETSCVIEWERDRAW,&isdraw));
59 #if defined(PETSC_HAVE_SAWS)
60   PetscCall(PetscObjectTypeCompare((PetscObject)viewer,PETSCVIEWERSAWS,&issaws));
61 #endif
62   if (isdraw) {
63     PetscDraw draw;
64     char      str[36];
65     PetscReal x,y,bottom,h;
66 
67     PetscCall(PetscViewerDrawGetDraw(viewer,0,&draw));
68     PetscCall(PetscDrawGetCurrentPoint(draw,&x,&y));
69     PetscCall(PetscStrncpy(str,"PetscDraw: ",sizeof(str)));
70     PetscCall(PetscStrlcat(str,((PetscObject)indraw)->type_name,sizeof(str)));
71     PetscCall(PetscDrawStringBoxed(draw,x,y,PETSC_DRAW_RED,PETSC_DRAW_BLACK,str,NULL,&h));
72     bottom = y - h;
73     PetscCall(PetscDrawPushCurrentPoint(draw,x,bottom));
74 #if defined(PETSC_HAVE_SAWS)
75   } else if (issaws) {
76     PetscMPIInt rank;
77 
78     PetscCall(PetscObjectName((PetscObject)indraw));
79     PetscCallMPI(MPI_Comm_rank(PETSC_COMM_WORLD,&rank));
80     if (!((PetscObject)indraw)->amsmem && rank == 0) {
81       PetscCall(PetscObjectViewSAWs((PetscObject)indraw,viewer));
82     }
83 #endif
84   } else if (indraw->ops->view) {
85     PetscCall((*indraw->ops->view)(indraw,viewer));
86   }
87   PetscFunctionReturn(0);
88 }
89 
90 /*@C
91    PetscDrawViewFromOptions - View from Options
92 
93    Collective on PetscDraw
94 
95    Input Parameters:
96 +  A - the PetscDraw context
97 .  obj - Optional object
98 -  name - command line option
99 
100    Level: intermediate
101 .seealso: `PetscDraw`, `PetscDrawView`, `PetscObjectViewFromOptions()`, `PetscDrawCreate()`
102 @*/
103 PetscErrorCode  PetscDrawViewFromOptions(PetscDraw A,PetscObject obj,const char name[])
104 {
105   PetscFunctionBegin;
106   PetscValidHeaderSpecific(A,PETSC_DRAW_CLASSID,1);
107   PetscCall(PetscObjectViewFromOptions((PetscObject)A,obj,name));
108   PetscFunctionReturn(0);
109 }
110 
111 /*@C
112    PetscDrawCreate - Creates a graphics context.
113 
114    Collective
115 
116    Input Parameters:
117 +  comm - MPI communicator
118 .  display - X display when using X Windows
119 .  title - optional title added to top of window
120 .  x,y - coordinates of lower left corner of window or PETSC_DECIDE
121 -  w, h - width and height of window or PETSC_DECIDE or PETSC_DRAW_HALF_SIZE, PETSC_DRAW_FULL_SIZE,
122           or PETSC_DRAW_THIRD_SIZE or PETSC_DRAW_QUARTER_SIZE
123 
124    Output Parameter:
125 .  draw - location to put the PetscDraw context
126 
127    Level: beginner
128 
129 .seealso: `PetscDrawSetType()`, `PetscDrawSetFromOptions()`, `PetscDrawDestroy()`, `PetscDrawSetType()`, `PetscDrawLGCreate()`, `PetscDrawSPCreate()`,
130           `PetscDrawViewPortsCreate()`, `PetscDrawViewPortsSet()`, `PetscDrawAxisCreate()`, `PetscDrawHGCreate()`, `PetscDrawBarCreate()`,
131           `PetscViewerDrawGetDraw()`, `PetscDrawSetFromOptions()`, `PetscDrawSetSave()`, `PetscDrawSetSaveMovie()`, `PetscDrawSetSaveFinalImage()`,
132           `PetscDrawOpenX()`, `PetscDrawOpenImage()`, `PetscDrawIsNull()`, `PetscDrawGetPopup()`, `PetscDrawCheckResizedWindow()`, `PetscDrawResizeWindow()`,
133           `PetscDrawGetWindowSize()`, `PetscDrawLine()`, `PetscDrawArrow()`, `PetscDrawLineSetWidth()`, `PetscDrawLineGetWidth()`, `PetscDrawMarker()`,
134           `PetscDrawPoint()`, `PetscDrawRectangle()`, `PetscDrawTriangle()`, `PetscDrawEllipse()`, `PetscDrawString()`, `PetscDrawStringCentered()`,
135           `PetscDrawStringBoxed()`, `PetscDrawStringVertical()`, `PetscDrawSetViewPort()`, `PetscDrawGetViewPort()`,
136           `PetscDrawSplitViewPort()`, `PetscDrawSetTitle()`, `PetscDrawAppendTitle()`, `PetscDrawGetTitle()`, `PetscDrawSetPause()`, `PetscDrawGetPause()`,
137           `PetscDrawPause()`, `PetscDrawSetDoubleBuffer()`, `PetscDrawClear()`, `PetscDrawFlush()`, `PetscDrawGetSingleton()`, `PetscDrawGetMouseButton()`,
138           `PetscDrawZoom()`, `PetscDrawGetBoundingBox()`
139 
140 @*/
141 PetscErrorCode  PetscDrawCreate(MPI_Comm comm,const char display[],const char title[],int x,int y,int w,int h,PetscDraw *indraw)
142 {
143   PetscDraw      draw;
144   PetscReal      dpause = 0.0;
145   PetscBool      flag;
146 
147   PetscFunctionBegin;
148   PetscCall(PetscDrawInitializePackage());
149   *indraw = NULL;
150   PetscCall(PetscHeaderCreate(draw,PETSC_DRAW_CLASSID,"Draw","Graphics","Draw",comm,PetscDrawDestroy,PetscDrawView));
151 
152   draw->data    = NULL;
153   PetscCall(PetscStrallocpy(display,&draw->display));
154   PetscCall(PetscStrallocpy(title,&draw->title));
155   draw->x       = x;
156   draw->y       = y;
157   draw->w       = w;
158   draw->h       = h;
159   draw->pause   = 0.0;
160   draw->coor_xl = 0.0;
161   draw->coor_xr = 1.0;
162   draw->coor_yl = 0.0;
163   draw->coor_yr = 1.0;
164   draw->port_xl = 0.0;
165   draw->port_xr = 1.0;
166   draw->port_yl = 0.0;
167   draw->port_yr = 1.0;
168   draw->popup   = NULL;
169 
170   PetscCall(PetscOptionsGetReal(NULL,NULL,"-draw_pause",&dpause,&flag));
171   if (flag) draw->pause = dpause;
172 
173   draw->savefilename   = NULL;
174   draw->saveimageext   = NULL;
175   draw->savemovieext   = NULL;
176   draw->savefilecount  = 0;
177   draw->savesinglefile = PETSC_FALSE;
178   draw->savemoviefps   = PETSC_DECIDE;
179 
180   PetscCall(PetscDrawSetCurrentPoint(draw,.5,.9));
181 
182   draw->boundbox_xl  = .5;
183   draw->boundbox_xr  = .5;
184   draw->boundbox_yl  = .9;
185   draw->boundbox_yr  = .9;
186 
187   *indraw = draw;
188   PetscFunctionReturn(0);
189 }
190 
191 /*@C
192    PetscDrawSetType - Builds graphics object for a particular implementation
193 
194    Collective on PetscDraw
195 
196    Input Parameters:
197 +  draw      - the graphics context
198 -  type      - for example, PETSC_DRAW_X
199 
200    Options Database Command:
201 .  -draw_type  <type> - Sets the type; use -help for a list of available methods (for instance, x)
202 
203    See PetscDrawSetFromOptions() for additional options database keys
204 
205    Level: intermediate
206 
207    Notes:
208    See "petsc/include/petscdraw.h" for available methods (for instance,
209    PETSC_DRAW_X, PETSC_DRAW_TIKZ or PETSC_DRAW_IMAGE)
210 
211 .seealso: `PetscDrawSetFromOptions()`, `PetscDrawCreate()`, `PetscDrawDestroy()`, `PetscDrawType`
212 @*/
213 PetscErrorCode  PetscDrawSetType(PetscDraw draw,PetscDrawType type)
214 {
215   PetscBool      match;
216   PetscBool      flg=PETSC_FALSE;
217   PetscErrorCode (*r)(PetscDraw);
218 
219   PetscFunctionBegin;
220   PetscValidHeaderSpecific(draw,PETSC_DRAW_CLASSID,1);
221   PetscValidCharPointer(type,2);
222 
223   PetscCall(PetscObjectTypeCompare((PetscObject)draw,type,&match));
224   if (match) PetscFunctionReturn(0);
225 
226   /*  User requests no graphics */
227   PetscCall(PetscOptionsHasName(((PetscObject)draw)->options,NULL,"-nox",&flg));
228 
229   /*
230      This is not ideal, but it allows codes to continue to run if X graphics
231    was requested but is not installed on this machine. Mostly this is for
232    testing.
233    */
234 #if !defined(PETSC_HAVE_X)
235   if (!flg) {
236     PetscCall(PetscStrcmp(type,PETSC_DRAW_X,&match));
237     if (match) {
238       PetscBool dontwarn = PETSC_TRUE;
239       flg  = PETSC_TRUE;
240       PetscCall(PetscOptionsHasName(NULL,NULL,"-nox_warning",&dontwarn));
241       if (!dontwarn) (*PetscErrorPrintf)("PETSc installed without X Windows on this machine\nproceeding without graphics\n");
242     }
243   }
244 #endif
245   if (flg) {
246     PetscCall(PetscStrcmp(type,"tikz",&flg));
247     if (!flg) type = PETSC_DRAW_NULL;
248   }
249 
250   PetscCall(PetscStrcmp(type,PETSC_DRAW_NULL,&match));
251   if (match) {
252     PetscCall(PetscOptionsHasName(NULL,NULL,"-draw_double_buffer",NULL));
253     PetscCall(PetscOptionsHasName(NULL,NULL,"-draw_virtual",NULL));
254     PetscCall(PetscOptionsHasName(NULL,NULL,"-draw_fast",NULL));
255     PetscCall(PetscOptionsHasName(NULL,NULL,"-draw_ports",NULL));
256     PetscCall(PetscOptionsHasName(NULL,NULL,"-draw_coordinates",NULL));
257   }
258 
259   PetscCall(PetscFunctionListFind(PetscDrawList,type,&r));
260   PetscCheck(r,PETSC_COMM_SELF,PETSC_ERR_ARG_UNKNOWN_TYPE,"Unknown PetscDraw type given: %s",type);
261   if (draw->ops->destroy) PetscCall((*draw->ops->destroy)(draw));
262   PetscCall(PetscMemzero(draw->ops,sizeof(struct _PetscDrawOps)));
263   PetscCall(PetscObjectChangeTypeName((PetscObject)draw,type));
264   PetscCall((*r)(draw));
265   PetscFunctionReturn(0);
266 }
267 
268 /*@C
269    PetscDrawGetType - Gets the PetscDraw type as a string from the PetscDraw object.
270 
271    Not Collective
272 
273    Input Parameter:
274 .  draw - Krylov context
275 
276    Output Parameters:
277 .  name - name of PetscDraw method
278 
279    Level: advanced
280 
281 .seealso: `PetscDrawSetType()`, `PetscDrawType`
282 
283 @*/
284 PetscErrorCode  PetscDrawGetType(PetscDraw draw,PetscDrawType *type)
285 {
286   PetscFunctionBegin;
287   PetscValidHeaderSpecific(draw,PETSC_DRAW_CLASSID,1);
288   PetscValidPointer(type,2);
289   *type = ((PetscObject)draw)->type_name;
290   PetscFunctionReturn(0);
291 }
292 
293 /*@C
294    PetscDrawRegister - Adds a method to the graphics package.
295 
296    Not Collective
297 
298    Input Parameters:
299 +  name_solver - name of a new user-defined graphics class
300 -  routine_create - routine to create method context
301 
302    Level: developer
303 
304    Notes:
305    PetscDrawRegister() may be called multiple times to add several user-defined graphics classes
306 
307    Sample usage:
308 .vb
309    PetscDrawRegister("my_draw_type", MyDrawCreate);
310 .ve
311 
312    Then, your specific graphics package can be chosen with the procedural interface via
313 $     PetscDrawSetType(ksp,"my_draw_type")
314    or at runtime via the option
315 $     -draw_type my_draw_type
316 
317 .seealso: `PetscDrawRegisterAll()`, `PetscDrawRegisterDestroy()`, `PetscDrawType`, `PetscDrawSetType()`
318 @*/
319 PetscErrorCode  PetscDrawRegister(const char *sname,PetscErrorCode (*function)(PetscDraw))
320 {
321   PetscFunctionBegin;
322   PetscCall(PetscDrawInitializePackage());
323   PetscCall(PetscFunctionListAdd(&PetscDrawList,sname,function));
324   PetscFunctionReturn(0);
325 }
326 
327 /*@C
328    PetscDrawSetOptionsPrefix - Sets the prefix used for searching for all
329    PetscDraw options in the database.
330 
331    Logically Collective on PetscDraw
332 
333    Input Parameters:
334 +  draw - the draw context
335 -  prefix - the prefix to prepend to all option names
336 
337    Level: advanced
338 
339 .seealso: `PetscDrawSetFromOptions()`, `PetscDrawCreate()`
340 @*/
341 PetscErrorCode  PetscDrawSetOptionsPrefix(PetscDraw draw,const char prefix[])
342 {
343   PetscFunctionBegin;
344   PetscValidHeaderSpecific(draw,PETSC_DRAW_CLASSID,1);
345   PetscCall(PetscObjectSetOptionsPrefix((PetscObject)draw,prefix));
346   PetscFunctionReturn(0);
347 }
348 
349 /*@
350    PetscDrawSetFromOptions - Sets the graphics type from the options database.
351       Defaults to a PETSc X Windows graphics.
352 
353    Collective on PetscDraw
354 
355    Input Parameter:
356 .     draw - the graphics context
357 
358    Options Database Keys:
359 +   -nox - do not use X graphics (ignore graphics calls, but run program correctly)
360 .   -nox_warning - when X Windows support is not installed this prevents the warning message from being printed
361 .   -draw_pause <pause amount> -- -1 indicates wait for mouse input, -2 indicates pause when window is to be destroyed
362 .   -draw_marker_type - <x,point>
363 .   -draw_save [optional filename] - (X Windows only) saves each image before it is cleared to a file
364 .   -draw_save_final_image [optional filename] - (X Windows only) saves the final image displayed in a window
365 .   -draw_save_movie - converts image files to a movie  at the end of the run. See PetscDrawSetSave()
366 .   -draw_save_single_file - saves each new image in the same file, normally each new image is saved in a new file with 'filename/filename_%d.ext'
367 .   -draw_save_on_clear - saves an image on each clear, mainly for debugging
368 -   -draw_save_on_flush - saves an image on each flush, mainly for debugging
369 
370    Level: intermediate
371 
372    Notes:
373     Must be called after PetscDrawCreate() before the PetscDraw is used.
374 
375 .seealso: `PetscDrawCreate()`, `PetscDrawSetType()`, `PetscDrawSetSave()`, `PetscDrawSetSaveFinalImage()`, `PetscDrawPause()`, `PetscDrawSetPause()`
376 
377 @*/
378 PetscErrorCode  PetscDrawSetFromOptions(PetscDraw draw)
379 {
380   PetscBool         flg,nox;
381   char              vtype[256];
382   const char        *def;
383 #if !defined(PETSC_USE_WINDOWS_GRAPHICS) && !defined(PETSC_HAVE_X)
384   PetscBool         warn;
385 #endif
386 
387   PetscFunctionBegin;
388   PetscValidHeaderSpecific(draw,PETSC_DRAW_CLASSID,1);
389 
390   PetscCall(PetscDrawRegisterAll());
391 
392   if (((PetscObject)draw)->type_name) def = ((PetscObject)draw)->type_name;
393   else {
394     PetscCall(PetscOptionsHasName(((PetscObject)draw)->options,NULL,"-nox",&nox));
395     def  = PETSC_DRAW_NULL;
396 #if defined(PETSC_USE_WINDOWS_GRAPHICS)
397     if (!nox) def = PETSC_DRAW_WIN32;
398 #elif defined(PETSC_HAVE_X)
399     if (!nox) def = PETSC_DRAW_X;
400 #else
401     PetscCall(PetscOptionsHasName(NULL,NULL,"-nox_warning",&warn));
402     if (!nox && !warn) (*PetscErrorPrintf)("PETSc installed without X Windows or Microsoft Graphics on this machine\nproceeding without graphics\n");
403 #endif
404   }
405   PetscObjectOptionsBegin((PetscObject)draw);
406   PetscCall(PetscOptionsFList("-draw_type","Type of graphical output","PetscDrawSetType",PetscDrawList,def,vtype,256,&flg));
407   if (flg) {
408     PetscCall(PetscDrawSetType(draw,vtype));
409   } else if (!((PetscObject)draw)->type_name) {
410     PetscCall(PetscDrawSetType(draw,def));
411   }
412   PetscCall(PetscOptionsName("-nox","Run without graphics","None",&nox));
413   {
414     char      filename[PETSC_MAX_PATH_LEN];
415     char      movieext[32];
416     PetscBool image,movie;
417     PetscCall(PetscSNPrintf(filename,sizeof(filename),"%s%s",draw->savefilename?draw->savefilename:"",draw->saveimageext?draw->saveimageext:""));
418     PetscCall(PetscSNPrintf(movieext,sizeof(movieext),"%s",draw->savemovieext?draw->savemovieext:""));
419     PetscCall(PetscOptionsString("-draw_save","Save graphics to image file","PetscDrawSetSave",filename,filename,sizeof(filename),&image));
420     PetscCall(PetscOptionsString("-draw_save_movie","Make a movie from saved images","PetscDrawSetSaveMovie",movieext,movieext,sizeof(movieext),&movie));
421     PetscCall(PetscOptionsInt("-draw_save_movie_fps","Set frames per second in saved movie",PETSC_FUNCTION_NAME,draw->savemoviefps,&draw->savemoviefps,NULL));
422     PetscCall(PetscOptionsBool("-draw_save_single_file","Each new image replaces previous image in file",PETSC_FUNCTION_NAME,draw->savesinglefile,&draw->savesinglefile,NULL));
423     if (image) PetscCall(PetscDrawSetSave(draw,filename));
424     if (movie) PetscCall(PetscDrawSetSaveMovie(draw,movieext));
425     PetscCall(PetscOptionsString("-draw_save_final_image","Save final graphics to image file","PetscDrawSetSaveFinalImage",filename,filename,sizeof(filename),&image));
426     if (image) PetscCall(PetscDrawSetSaveFinalImage(draw,filename));
427     PetscCall(PetscOptionsBool("-draw_save_on_clear","Save graphics to file on each clear",PETSC_FUNCTION_NAME,draw->saveonclear,&draw->saveonclear,NULL));
428     PetscCall(PetscOptionsBool("-draw_save_on_flush","Save graphics to file on each flush",PETSC_FUNCTION_NAME,draw->saveonflush,&draw->saveonflush,NULL));
429   }
430   PetscCall(PetscOptionsReal("-draw_pause","Amount of time that program pauses after plots","PetscDrawSetPause",draw->pause,&draw->pause,NULL));
431   PetscCall(PetscOptionsEnum("-draw_marker_type","Type of marker to use on plots","PetscDrawSetMarkerType",PetscDrawMarkerTypes,(PetscEnum)draw->markertype,(PetscEnum *)&draw->markertype,NULL));
432 
433   /* process any options handlers added with PetscObjectAddOptionsHandler() */
434   PetscCall(PetscObjectProcessOptionsHandlers(PetscOptionsObject,(PetscObject)draw));
435 
436   PetscCall(PetscDrawViewFromOptions(draw,NULL,"-draw_view"));
437   PetscOptionsEnd();
438   PetscFunctionReturn(0);
439 }
440