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