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