xref: /petsc/src/sys/classes/draw/interface/drawreg.c (revision ce6b3536d5fd46c99c6df19dc764ec34b4d2762c)
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 - 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 .  draw - location to put the `PetscDraw` context
121 
122    Level: beginner
123 
124 .seealso: `PetscDrawSetType()`, `PetscDrawSetFromOptions()`, `PetscDrawDestroy()`, `PetscDrawSetType()`, `PetscDrawLGCreate()`, `PetscDrawSPCreate()`,
125           `PetscDrawViewPortsCreate()`, `PetscDrawViewPortsSet()`, `PetscDrawAxisCreate()`, `PetscDrawHGCreate()`, `PetscDrawBarCreate()`,
126           `PetscViewerDrawGetDraw()`, `PetscDrawSetFromOptions()`, `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   PetscValidCharPointer(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 .  name - 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   PetscValidPointer(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 +  name_solver - name of a new user-defined graphics class
293 -  routine_create - 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    Sample 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