xref: /petsc/src/sys/classes/draw/interface/drawreg.c (revision 2ff79c18c26c94ed8cb599682f680f231dca6444)
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 /*@
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 /*@
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 /*@
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   PetscAssertPointer(indraw, 8);
143   PetscCall(PetscDrawInitializePackage());
144 
145   PetscCall(PetscHeaderCreate(draw, PETSC_DRAW_CLASSID, "Draw", "Graphics", "Draw", comm, PetscDrawDestroy, PetscDrawView));
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 /*@
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 /*@
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, No Fortran Support
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 .vb
307   PetscDrawSetType(ksp, "my_draw_type")
308 .ve
309   or at runtime via the option
310 .vb
311   -draw_type my_draw_type
312 .ve
313 
314 .seealso: `PetscDraw`, `PetscDrawRegisterAll()`, `PetscDrawRegisterDestroy()`, `PetscDrawType`, `PetscDrawSetType()`
315 @*/
316 PetscErrorCode PetscDrawRegister(const char *sname, PetscErrorCode (*function)(PetscDraw))
317 {
318   PetscFunctionBegin;
319   PetscCall(PetscDrawInitializePackage());
320   PetscCall(PetscFunctionListAdd(&PetscDrawList, sname, function));
321   PetscFunctionReturn(PETSC_SUCCESS);
322 }
323 
324 /*@
325   PetscDrawSetOptionsPrefix - Sets the prefix used for searching for all
326   `PetscDraw` options in the database.
327 
328   Logically Collective
329 
330   Input Parameters:
331 + draw   - the draw context
332 - prefix - the prefix to prepend to all option names
333 
334   Level: advanced
335 
336 .seealso: `PetscDraw`, `PetscDrawSetFromOptions()`, `PetscDrawCreate()`
337 @*/
338 PetscErrorCode PetscDrawSetOptionsPrefix(PetscDraw draw, const char prefix[])
339 {
340   PetscFunctionBegin;
341   PetscValidHeaderSpecific(draw, PETSC_DRAW_CLASSID, 1);
342   PetscCall(PetscObjectSetOptionsPrefix((PetscObject)draw, prefix));
343   PetscFunctionReturn(PETSC_SUCCESS);
344 }
345 
346 /*@
347   PetscDrawSetFromOptions - Sets the graphics type from the options database.
348   Defaults to a PETSc X Windows graphics.
349 
350   Collective
351 
352   Input Parameter:
353 . draw - the graphics context
354 
355   Options Database Keys:
356 + -nox                                       - do not use X graphics (ignore graphics calls, but run program correctly)
357 . -nox_warning                               - when X Windows support is not installed this prevents the warning message from being printed
358 . -draw_pause <pause amount>                 - - -1 indicates wait for mouse input, -2 indicates pause when window is to be destroyed
359 . -draw_marker_type                          - <x,point>
360 . -draw_save [optional filename]             - (X Windows only) saves each image before it is cleared to a file
361 . -draw_save_final_image [optional filename] - (X Windows only) saves the final image displayed in a window
362 . -draw_save_movie                           - converts image files to a movie  at the end of the run. See PetscDrawSetSave()
363 . -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'
364 . -draw_save_on_clear                        - saves an image on each clear, mainly for debugging
365 - -draw_save_on_flush                        - saves an image on each flush, mainly for debugging
366 
367   Level: intermediate
368 
369   Note:
370   Must be called after `PetscDrawCreate()` before the `PetscDraw` is used.
371 
372 .seealso: `PetscDraw`, `PetscDrawCreate()`, `PetscDrawSetType()`, `PetscDrawSetSave()`, `PetscDrawSetSaveFinalImage()`, `PetscDrawPause()`, `PetscDrawSetPause()`
373 @*/
374 PetscErrorCode PetscDrawSetFromOptions(PetscDraw draw)
375 {
376   PetscBool   flg, nox;
377   char        vtype[256];
378   const char *def;
379 #if !defined(PETSC_USE_WINDOWS_GRAPHICS) && !defined(PETSC_HAVE_X)
380   PetscBool warn;
381 #endif
382 
383   PetscFunctionBegin;
384   PetscValidHeaderSpecific(draw, PETSC_DRAW_CLASSID, 1);
385 
386   PetscCall(PetscDrawRegisterAll());
387 
388   if (((PetscObject)draw)->type_name) def = ((PetscObject)draw)->type_name;
389   else {
390     PetscCall(PetscOptionsHasName(((PetscObject)draw)->options, NULL, "-nox", &nox));
391     def = PETSC_DRAW_NULL;
392 #if defined(PETSC_USE_WINDOWS_GRAPHICS)
393     if (!nox) def = PETSC_DRAW_WIN32;
394 #elif defined(PETSC_HAVE_X)
395     if (!nox) def = PETSC_DRAW_X;
396 #else
397     PetscCall(PetscOptionsHasName(NULL, NULL, "-nox_warning", &warn));
398     if (!nox && !warn) PetscCall((*PetscErrorPrintf)("PETSc installed without X Windows or Microsoft Graphics on this machine\nproceeding without graphics\n"));
399 #endif
400   }
401   PetscObjectOptionsBegin((PetscObject)draw);
402   PetscCall(PetscOptionsFList("-draw_type", "Type of graphical output", "PetscDrawSetType", PetscDrawList, def, vtype, 256, &flg));
403   if (flg) {
404     PetscCall(PetscDrawSetType(draw, vtype));
405   } else if (!((PetscObject)draw)->type_name) {
406     PetscCall(PetscDrawSetType(draw, def));
407   }
408   PetscCall(PetscOptionsName("-nox", "Run without graphics", "None", &nox));
409   {
410     char      filename[PETSC_MAX_PATH_LEN];
411     char      movieext[32];
412     PetscBool image, movie;
413     PetscCall(PetscSNPrintf(filename, sizeof(filename), "%s%s", draw->savefilename ? draw->savefilename : "", draw->saveimageext ? draw->saveimageext : ""));
414     PetscCall(PetscSNPrintf(movieext, sizeof(movieext), "%s", draw->savemovieext ? draw->savemovieext : ""));
415     PetscCall(PetscOptionsString("-draw_save", "Save graphics to image file", "PetscDrawSetSave", filename, filename, sizeof(filename), &image));
416     PetscCall(PetscOptionsString("-draw_save_movie", "Make a movie from saved images", "PetscDrawSetSaveMovie", movieext, movieext, sizeof(movieext), &movie));
417     PetscCall(PetscOptionsInt("-draw_save_movie_fps", "Set frames per second in saved movie", PETSC_FUNCTION_NAME, draw->savemoviefps, &draw->savemoviefps, NULL));
418     PetscCall(PetscOptionsBool("-draw_save_single_file", "Each new image replaces previous image in file", PETSC_FUNCTION_NAME, draw->savesinglefile, &draw->savesinglefile, NULL));
419     if (image) PetscCall(PetscDrawSetSave(draw, filename));
420     if (movie) PetscCall(PetscDrawSetSaveMovie(draw, movieext));
421     PetscCall(PetscOptionsString("-draw_save_final_image", "Save final graphics to image file", "PetscDrawSetSaveFinalImage", filename, filename, sizeof(filename), &image));
422     if (image) PetscCall(PetscDrawSetSaveFinalImage(draw, filename));
423     PetscCall(PetscOptionsBool("-draw_save_on_clear", "Save graphics to file on each clear", PETSC_FUNCTION_NAME, draw->saveonclear, &draw->saveonclear, NULL));
424     PetscCall(PetscOptionsBool("-draw_save_on_flush", "Save graphics to file on each flush", PETSC_FUNCTION_NAME, draw->saveonflush, &draw->saveonflush, NULL));
425   }
426   PetscCall(PetscOptionsReal("-draw_pause", "Amount of time that program pauses after plots", "PetscDrawSetPause", draw->pause, &draw->pause, NULL));
427   PetscCall(PetscOptionsEnum("-draw_marker_type", "Type of marker to use on plots", "PetscDrawSetMarkerType", PetscDrawMarkerTypes, (PetscEnum)draw->markertype, (PetscEnum *)&draw->markertype, NULL));
428 
429   /* process any options handlers added with PetscObjectAddOptionsHandler() */
430   PetscCall(PetscObjectProcessOptionsHandlers((PetscObject)draw, PetscOptionsObject));
431 
432   PetscCall(PetscDrawViewFromOptions(draw, NULL, "-draw_view"));
433   PetscOptionsEnd();
434   PetscFunctionReturn(PETSC_SUCCESS);
435 }
436