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