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