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