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