xref: /petsc/src/sys/classes/draw/interface/draw.c (revision fbf9dbe564678ed6eff1806adbc4c4f01b9743f4)
1 
2 #include <petsc/private/drawimpl.h> /*I "petscdraw.h" I*/
3 #include <petscviewer.h>
4 
5 PetscClassId PETSC_DRAW_CLASSID;
6 
7 static PetscBool PetscDrawPackageInitialized = PETSC_FALSE;
8 /*@C
9   PetscDrawFinalizePackage - This function destroys everything in the Petsc interface to the `PetscDraw` package. It is
10   called from `PetscFinalize()`.
11 
12   Level: developer
13 
14 .seealso: `PetscDraw`, `PetscFinalize()`
15 @*/
16 PetscErrorCode PetscDrawFinalizePackage(void)
17 {
18   PetscFunctionBegin;
19   PetscCall(PetscFunctionListDestroy(&PetscDrawList));
20   PetscDrawPackageInitialized = PETSC_FALSE;
21   PetscDrawRegisterAllCalled  = PETSC_FALSE;
22   PetscFunctionReturn(PETSC_SUCCESS);
23 }
24 
25 /*@C
26   PetscInitializeDrawPackage - This function initializes everything in the `PetscDraw` package. It is called
27   from PetscDLLibraryRegister_petsc() when using dynamic libraries, and on the call to `PetscInitialize()`
28   when using shared or static libraries.
29 
30   Level: developer
31 
32 .seealso: `PetscDraw`, `PetscInitialize()`
33 @*/
34 PetscErrorCode PetscDrawInitializePackage(void)
35 {
36   char      logList[256];
37   PetscBool opt, pkg;
38 
39   PetscFunctionBegin;
40   if (PetscDrawPackageInitialized) PetscFunctionReturn(PETSC_SUCCESS);
41   PetscDrawPackageInitialized = PETSC_TRUE;
42   /* Register Classes */
43   PetscCall(PetscClassIdRegister("Draw", &PETSC_DRAW_CLASSID));
44   PetscCall(PetscClassIdRegister("Draw Axis", &PETSC_DRAWAXIS_CLASSID));
45   PetscCall(PetscClassIdRegister("Line Graph", &PETSC_DRAWLG_CLASSID));
46   PetscCall(PetscClassIdRegister("Histogram", &PETSC_DRAWHG_CLASSID));
47   PetscCall(PetscClassIdRegister("Bar Graph", &PETSC_DRAWBAR_CLASSID));
48   PetscCall(PetscClassIdRegister("Scatter Plot", &PETSC_DRAWSP_CLASSID));
49   /* Register Constructors */
50   PetscCall(PetscDrawRegisterAll());
51   /* Process Info */
52   {
53     PetscClassId classids[6];
54 
55     classids[0] = PETSC_DRAW_CLASSID;
56     classids[1] = PETSC_DRAWAXIS_CLASSID;
57     classids[2] = PETSC_DRAWLG_CLASSID;
58     classids[3] = PETSC_DRAWHG_CLASSID;
59     classids[4] = PETSC_DRAWBAR_CLASSID;
60     classids[5] = PETSC_DRAWSP_CLASSID;
61     PetscCall(PetscInfoProcessClass("draw", 6, classids));
62   }
63   /* Process summary exclusions */
64   PetscCall(PetscOptionsGetString(NULL, NULL, "-log_exclude", logList, sizeof(logList), &opt));
65   if (opt) {
66     PetscCall(PetscStrInList("draw", logList, ',', &pkg));
67     if (pkg) {
68       PetscCall(PetscLogEventExcludeClass(PETSC_DRAW_CLASSID));
69       PetscCall(PetscLogEventExcludeClass(PETSC_DRAWAXIS_CLASSID));
70       PetscCall(PetscLogEventExcludeClass(PETSC_DRAWLG_CLASSID));
71       PetscCall(PetscLogEventExcludeClass(PETSC_DRAWHG_CLASSID));
72       PetscCall(PetscLogEventExcludeClass(PETSC_DRAWBAR_CLASSID));
73       PetscCall(PetscLogEventExcludeClass(PETSC_DRAWSP_CLASSID));
74     }
75   }
76   /* Register package finalizer */
77   PetscCall(PetscRegisterFinalize(PetscDrawFinalizePackage));
78   PetscFunctionReturn(PETSC_SUCCESS);
79 }
80 
81 /*@
82    PetscDrawResizeWindow - Allows one to resize a window from a program.
83 
84    Collective
85 
86    Input Parameters:
87 +  draw - the window
88 .  w - the new width of the window
89 -  h - the new height of the window
90 
91    Level: intermediate
92 
93 .seealso: `PetscDraw`, `PetscDrawCheckResizedWindow()`
94 @*/
95 PetscErrorCode PetscDrawResizeWindow(PetscDraw draw, int w, int h)
96 {
97   PetscFunctionBegin;
98   PetscValidHeaderSpecific(draw, PETSC_DRAW_CLASSID, 1);
99   PetscValidLogicalCollectiveInt(draw, w, 2);
100   PetscValidLogicalCollectiveInt(draw, h, 3);
101   PetscTryTypeMethod(draw, resizewindow, w, h);
102   PetscFunctionReturn(PETSC_SUCCESS);
103 }
104 
105 /*@
106    PetscDrawGetWindowSize - Gets the size of the window.
107 
108    Not Collective
109 
110    Input Parameter:
111 .  draw - the window
112 
113    Output Parameters:
114 +  w - the window width
115 -  h - the window height
116 
117    Level: intermediate
118 
119 .seealso: `PetscDraw`, `PetscDrawResizeWindow()`, `PetscDrawCheckResizedWindow()`
120 @*/
121 PetscErrorCode PetscDrawGetWindowSize(PetscDraw draw, int *w, int *h)
122 {
123   PetscFunctionBegin;
124   PetscValidHeaderSpecific(draw, PETSC_DRAW_CLASSID, 1);
125   if (w) PetscValidPointer(w, 2);
126   if (h) PetscValidPointer(h, 3);
127   if (w) *w = draw->w;
128   if (h) *h = draw->h;
129   PetscFunctionReturn(PETSC_SUCCESS);
130 }
131 
132 /*@
133    PetscDrawCheckResizedWindow - Checks if the user has resized the window.
134 
135    Collective
136 
137    Input Parameter:
138 .  draw - the window
139 
140    Level: advanced
141 
142 .seealso: `PetscDraw`, `PetscDrawResizeWindow()`
143 @*/
144 PetscErrorCode PetscDrawCheckResizedWindow(PetscDraw draw)
145 {
146   PetscFunctionBegin;
147   PetscValidHeaderSpecific(draw, PETSC_DRAW_CLASSID, 1);
148   PetscTryTypeMethod(draw, checkresizedwindow);
149   PetscFunctionReturn(PETSC_SUCCESS);
150 }
151 
152 /*@C
153    PetscDrawGetTitle - Gets pointer to title of a `PetscDraw` context.
154 
155    Not Collective
156 
157    Input Parameter:
158 .  draw - the graphics context
159 
160    Output Parameter:
161 .  title - the title
162 
163    Level: intermediate
164 
165 .seealso: `PetscDraw`, `PetscDrawSetTitle()`
166 @*/
167 PetscErrorCode PetscDrawGetTitle(PetscDraw draw, const char *title[])
168 {
169   PetscFunctionBegin;
170   PetscValidHeaderSpecific(draw, PETSC_DRAW_CLASSID, 1);
171   PetscValidPointer(title, 2);
172   *title = draw->title;
173   PetscFunctionReturn(PETSC_SUCCESS);
174 }
175 
176 /*@C
177    PetscDrawSetTitle - Sets the title of a `PetscDraw` context.
178 
179    Collective
180 
181    Input Parameters:
182 +  draw - the graphics context
183 -  title - the title
184 
185    Level: intermediate
186 
187    Notes:
188    The title is positioned in the windowing system title bar for the window. Hence it will not be saved with -draw_save
189    in the image.
190 
191    A copy of the string is made, so you may destroy the
192    title string after calling this routine.
193 
194    You can use `PetscDrawAxisSetLabels()` to indicate a title within the window
195 
196 .seealso: `PetscDraw`, `PetscDrawGetTitle()`, `PetscDrawAppendTitle()`
197 @*/
198 PetscErrorCode PetscDrawSetTitle(PetscDraw draw, const char title[])
199 {
200   PetscFunctionBegin;
201   PetscValidHeaderSpecific(draw, PETSC_DRAW_CLASSID, 1);
202   PetscValidCharPointer(title, 2);
203   PetscCall(PetscFree(draw->title));
204   PetscCall(PetscStrallocpy(title, &draw->title));
205   PetscTryTypeMethod(draw, settitle, draw->title);
206   PetscFunctionReturn(PETSC_SUCCESS);
207 }
208 
209 /*@C
210    PetscDrawAppendTitle - Appends to the title of a `PetscDraw` context.
211 
212    Collective
213 
214    Input Parameters:
215 +  draw - the graphics context
216 -  title - the title
217 
218    Level: advanced
219 
220    Note:
221    A copy of the string is made, so you may destroy the
222    title string after calling this routine.
223 
224 .seealso: `PetscDraw`, `PetscDrawSetTitle()`, `PetscDrawGetTitle()`
225 @*/
226 PetscErrorCode PetscDrawAppendTitle(PetscDraw draw, const char title[])
227 {
228   PetscFunctionBegin;
229   PetscValidHeaderSpecific(draw, PETSC_DRAW_CLASSID, 1);
230   if (title) PetscValidCharPointer(title, 2);
231   if (!title || !title[0]) PetscFunctionReturn(PETSC_SUCCESS);
232 
233   if (draw->title) {
234     size_t len1, len2, new_len;
235     PetscCall(PetscStrlen(draw->title, &len1));
236     PetscCall(PetscStrlen(title, &len2));
237     new_len = len1 + len2 + 1;
238     PetscCall(PetscRealloc(new_len * sizeof(*(draw->title)), &draw->title));
239     PetscCall(PetscStrncpy(draw->title + len1, title, len2 + 1));
240   } else {
241     PetscCall(PetscStrallocpy(title, &draw->title));
242   }
243   PetscTryTypeMethod(draw, settitle, draw->title);
244   PetscFunctionReturn(PETSC_SUCCESS);
245 }
246 
247 static PetscErrorCode PetscDrawDestroy_Private(PetscDraw draw)
248 {
249   PetscFunctionBegin;
250   if (!draw->ops->save && !draw->ops->getimage) PetscFunctionReturn(PETSC_SUCCESS);
251   PetscCall(PetscDrawSaveMovie(draw));
252   if (draw->savefinalfilename) {
253     draw->savesinglefile = PETSC_TRUE;
254     PetscCall(PetscDrawSetSave(draw, draw->savefinalfilename));
255     PetscCall(PetscDrawSave(draw));
256   }
257   PetscCall(PetscBarrier((PetscObject)draw));
258   PetscFunctionReturn(PETSC_SUCCESS);
259 }
260 
261 /*@
262    PetscDrawDestroy - Deletes a draw context.
263 
264    Collective
265 
266    Input Parameter:
267 .  draw - the drawing context
268 
269    Level: beginner
270 
271 .seealso: `PetscDraw`, `PetscDrawCreate()`
272 @*/
273 PetscErrorCode PetscDrawDestroy(PetscDraw *draw)
274 {
275   PetscFunctionBegin;
276   if (!*draw) PetscFunctionReturn(PETSC_SUCCESS);
277   PetscValidHeaderSpecific(*draw, PETSC_DRAW_CLASSID, 1);
278   if (--((PetscObject)(*draw))->refct > 0) PetscFunctionReturn(PETSC_SUCCESS);
279 
280   if ((*draw)->pause == -2) {
281     (*draw)->pause = -1;
282     PetscCall(PetscDrawPause(*draw));
283   }
284 
285   /* if memory was published then destroy it */
286   PetscCall(PetscObjectSAWsViewOff((PetscObject)*draw));
287 
288   PetscCall(PetscDrawDestroy_Private(*draw));
289 
290   if ((*draw)->ops->destroy) PetscCall((*(*draw)->ops->destroy)(*draw));
291   PetscCall(PetscDrawDestroy(&(*draw)->popup));
292   PetscCall(PetscFree((*draw)->title));
293   PetscCall(PetscFree((*draw)->display));
294   PetscCall(PetscFree((*draw)->savefilename));
295   PetscCall(PetscFree((*draw)->saveimageext));
296   PetscCall(PetscFree((*draw)->savemovieext));
297   PetscCall(PetscFree((*draw)->savefinalfilename));
298   PetscCall(PetscHeaderDestroy(draw));
299   PetscFunctionReturn(PETSC_SUCCESS);
300 }
301 
302 /*@
303    PetscDrawGetPopup - Creates a popup window associated with a `PetscDraw` window.
304 
305    Collective
306 
307    Input Parameter:
308 .  draw - the original window
309 
310    Output Parameter:
311 .  popup - the new popup window
312 
313    Level: advanced
314 
315 .seealso: `PetscDraw`, `PetscDrawScalePopup()`, `PetscDrawCreate()`
316 @*/
317 PetscErrorCode PetscDrawGetPopup(PetscDraw draw, PetscDraw *popup)
318 {
319   PetscFunctionBegin;
320   PetscValidHeaderSpecific(draw, PETSC_DRAW_CLASSID, 1);
321   PetscValidPointer(popup, 2);
322 
323   if (draw->popup) *popup = draw->popup;
324   else if (draw->ops->getpopup) {
325     PetscUseTypeMethod(draw, getpopup, popup);
326     if (*popup) {
327       PetscCall(PetscObjectSetOptionsPrefix((PetscObject)*popup, "popup_"));
328       (*popup)->pause = 0.0;
329       PetscCall(PetscDrawSetFromOptions(*popup));
330     }
331   } else *popup = NULL;
332   PetscFunctionReturn(PETSC_SUCCESS);
333 }
334 
335 /*@C
336   PetscDrawSetDisplay - Sets the display where a `PetscDraw` object will be displayed
337 
338   Input Parameters:
339 + draw - the drawing context
340 - display - the X windows display
341 
342   Level: advanced
343 
344 .seealso: `PetscDraw`, `PetscDrawOpenX()`, `PetscDrawCreate()`
345 @*/
346 PetscErrorCode PetscDrawSetDisplay(PetscDraw draw, const char display[])
347 {
348   PetscFunctionBegin;
349   PetscCall(PetscFree(draw->display));
350   PetscCall(PetscStrallocpy(display, &draw->display));
351   PetscFunctionReturn(PETSC_SUCCESS);
352 }
353 
354 /*@
355    PetscDrawSetDoubleBuffer - Sets a window to be double buffered.
356 
357    Logically Collective
358 
359    Input Parameter:
360 .  draw - the drawing context
361 
362    Level: intermediate
363 
364 .seealso: `PetscDraw`, `PetscDrawOpenX()`, `PetscDrawCreate()`
365 @*/
366 PetscErrorCode PetscDrawSetDoubleBuffer(PetscDraw draw)
367 {
368   PetscFunctionBegin;
369   PetscValidHeaderSpecific(draw, PETSC_DRAW_CLASSID, 1);
370   PetscTryTypeMethod(draw, setdoublebuffer);
371   PetscFunctionReturn(PETSC_SUCCESS);
372 }
373 
374 /*@C
375    PetscDrawGetSingleton - Gain access to a `PetscDraw` object as if it were owned
376         by the one process.
377 
378    Collective
379 
380    Input Parameter:
381 .  draw - the original window
382 
383    Output Parameter:
384 .  sdraw - the singleton window
385 
386    Level: advanced
387 
388 .seealso: `PetscDraw`, `PetscDrawRestoreSingleton()`, `PetscViewerGetSingleton()`, `PetscViewerRestoreSingleton()`
389 @*/
390 PetscErrorCode PetscDrawGetSingleton(PetscDraw draw, PetscDraw *sdraw)
391 {
392   PetscMPIInt size;
393 
394   PetscFunctionBegin;
395   PetscValidHeaderSpecific(draw, PETSC_DRAW_CLASSID, 1);
396   PetscValidPointer(sdraw, 2);
397 
398   PetscCallMPI(MPI_Comm_size(PetscObjectComm((PetscObject)draw), &size));
399   if (size == 1) {
400     PetscCall(PetscObjectReference((PetscObject)draw));
401     *sdraw = draw;
402   } else {
403     if (draw->ops->getsingleton) {
404       PetscUseTypeMethod(draw, getsingleton, sdraw);
405     } else SETERRQ(PETSC_COMM_SELF, PETSC_ERR_SUP, "Cannot get singleton for this type %s of draw object", ((PetscObject)draw)->type_name);
406   }
407   PetscFunctionReturn(PETSC_SUCCESS);
408 }
409 
410 /*@C
411    PetscDrawRestoreSingleton - Remove access to a `PetscDraw` object obtained with `PetscDrawGetSingleton()`
412         by the one process.
413 
414    Collective
415 
416    Input Parameters:
417 +  draw - the original window
418 -  sdraw - the singleton window
419 
420    Level: advanced
421 
422 .seealso: `PetscDraw`, `PetscDrawGetSingleton()`, `PetscViewerGetSingleton()`, `PetscViewerRestoreSingleton()`
423 @*/
424 PetscErrorCode PetscDrawRestoreSingleton(PetscDraw draw, PetscDraw *sdraw)
425 {
426   PetscMPIInt size;
427 
428   PetscFunctionBegin;
429   PetscValidHeaderSpecific(draw, PETSC_DRAW_CLASSID, 1);
430   PetscValidPointer(sdraw, 2);
431   PetscValidHeaderSpecific(*sdraw, PETSC_DRAW_CLASSID, 2);
432 
433   PetscCallMPI(MPI_Comm_size(PetscObjectComm((PetscObject)draw), &size));
434   if (size == 1) {
435     if (draw == *sdraw) {
436       PetscCall(PetscObjectDereference((PetscObject)draw));
437       *sdraw = NULL;
438     } else SETERRQ(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Cannot restore singleton, it is not the parent draw");
439   } else PetscUseTypeMethod(draw, restoresingleton, sdraw);
440   PetscFunctionReturn(PETSC_SUCCESS);
441 }
442 
443 /*@C
444   PetscDrawSetVisible - Sets if the drawing surface (the 'window') is visible on its display.
445 
446   Input Parameters:
447 + draw - the drawing window
448 - visible - if the surface should be visible
449 
450   Level: intermediate
451 
452 .seealso: `PetscDraw`
453 @*/
454 PetscErrorCode PetscDrawSetVisible(PetscDraw draw, PetscBool visible)
455 {
456   PetscFunctionBegin;
457   PetscValidHeaderSpecific(draw, PETSC_DRAW_CLASSID, 1);
458   PetscTryTypeMethod(draw, setvisible, visible);
459   PetscFunctionReturn(PETSC_SUCCESS);
460 }
461