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