xref: /petsc/src/sys/classes/draw/interface/draw.c (revision a69119a591a03a9d906b29c0a4e9802e4d7c9795)
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 Draw package. It is
13   called from PetscFinalize().
14 
15   Level: developer
16 
17 .seealso: `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: `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 PetscDraw
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: `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: `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 PetscDraw
133 
134    Input Parameter:
135 .  draw - the window
136 
137    Level: advanced
138 
139 .seealso: `PetscDrawResizeWindow()`
140 
141 @*/
142 PetscErrorCode PetscDrawCheckResizedWindow(PetscDraw draw) {
143   PetscFunctionBegin;
144   PetscValidHeaderSpecific(draw, PETSC_DRAW_CLASSID, 1);
145   PetscTryTypeMethod(draw, checkresizedwindow);
146   PetscFunctionReturn(0);
147 }
148 
149 /*@C
150    PetscDrawGetTitle - Gets pointer to title of a PetscDraw context.
151 
152    Not collective
153 
154    Input Parameter:
155 .  draw - the graphics context
156 
157    Output Parameter:
158 .  title - the title
159 
160    Level: intermediate
161 
162 .seealso: `PetscDrawSetTitle()`
163 @*/
164 PetscErrorCode PetscDrawGetTitle(PetscDraw draw, const char *title[]) {
165   PetscFunctionBegin;
166   PetscValidHeaderSpecific(draw, PETSC_DRAW_CLASSID, 1);
167   PetscValidPointer(title, 2);
168   *title = draw->title;
169   PetscFunctionReturn(0);
170 }
171 
172 /*@C
173    PetscDrawSetTitle - Sets the title of a PetscDraw context.
174 
175    Collective on PetscDraw
176 
177    Input Parameters:
178 +  draw - the graphics context
179 -  title - the title
180 
181    Level: intermediate
182 
183    Note: 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: `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 PetscDraw
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: `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 PetscDraw
260 
261    Input Parameters:
262 .  draw - the drawing context
263 
264    Level: beginner
265 
266 .seealso: `PetscDrawCreate()`
267 
268 @*/
269 PetscErrorCode PetscDrawDestroy(PetscDraw *draw) {
270   PetscFunctionBegin;
271   if (!*draw) PetscFunctionReturn(0);
272   PetscValidHeaderSpecific(*draw, PETSC_DRAW_CLASSID, 1);
273   if (--((PetscObject)(*draw))->refct > 0) PetscFunctionReturn(0);
274 
275   if ((*draw)->pause == -2) {
276     (*draw)->pause = -1;
277     PetscCall(PetscDrawPause(*draw));
278   }
279 
280   /* if memory was published then destroy it */
281   PetscCall(PetscObjectSAWsViewOff((PetscObject)*draw));
282 
283   PetscCall(PetscDrawDestroy_Private(*draw));
284 
285   if ((*draw)->ops->destroy) PetscCall((*(*draw)->ops->destroy)(*draw));
286   PetscCall(PetscDrawDestroy(&(*draw)->popup));
287   PetscCall(PetscFree((*draw)->title));
288   PetscCall(PetscFree((*draw)->display));
289   PetscCall(PetscFree((*draw)->savefilename));
290   PetscCall(PetscFree((*draw)->saveimageext));
291   PetscCall(PetscFree((*draw)->savemovieext));
292   PetscCall(PetscFree((*draw)->savefinalfilename));
293   PetscCall(PetscHeaderDestroy(draw));
294   PetscFunctionReturn(0);
295 }
296 
297 /*@
298    PetscDrawGetPopup - Creates a popup window associated with a PetscDraw window.
299 
300    Collective on PetscDraw
301 
302    Input Parameter:
303 .  draw - the original window
304 
305    Output Parameter:
306 .  popup - the new popup window
307 
308    Level: advanced
309 
310 .seealso: `PetscDrawScalePopup()`, `PetscDrawCreate()`
311 
312 @*/
313 PetscErrorCode PetscDrawGetPopup(PetscDraw draw, PetscDraw *popup) {
314   PetscFunctionBegin;
315   PetscValidHeaderSpecific(draw, PETSC_DRAW_CLASSID, 1);
316   PetscValidPointer(popup, 2);
317 
318   if (draw->popup) *popup = draw->popup;
319   else if (draw->ops->getpopup) {
320     PetscUseTypeMethod(draw, getpopup, popup);
321     if (*popup) {
322       PetscCall(PetscObjectSetOptionsPrefix((PetscObject)*popup, "popup_"));
323       (*popup)->pause = 0.0;
324       PetscCall(PetscDrawSetFromOptions(*popup));
325     }
326   } else *popup = NULL;
327   PetscFunctionReturn(0);
328 }
329 
330 /*@C
331   PetscDrawSetDisplay - Sets the display where a PetscDraw object will be displayed
332 
333   Input Parameters:
334 + draw - the drawing context
335 - display - the X windows display
336 
337   Level: advanced
338 
339 .seealso: `PetscDrawCreate()`
340 
341 @*/
342 PetscErrorCode PetscDrawSetDisplay(PetscDraw draw, const char display[]) {
343   PetscFunctionBegin;
344   PetscCall(PetscFree(draw->display));
345   PetscCall(PetscStrallocpy(display, &draw->display));
346   PetscFunctionReturn(0);
347 }
348 
349 /*@
350    PetscDrawSetDoubleBuffer - Sets a window to be double buffered.
351 
352    Logically Collective on PetscDraw
353 
354    Input Parameter:
355 .  draw - the drawing context
356 
357    Level: intermediate
358 
359 @*/
360 PetscErrorCode PetscDrawSetDoubleBuffer(PetscDraw draw) {
361   PetscFunctionBegin;
362   PetscValidHeaderSpecific(draw, PETSC_DRAW_CLASSID, 1);
363   PetscTryTypeMethod(draw, setdoublebuffer);
364   PetscFunctionReturn(0);
365 }
366 
367 /*@C
368    PetscDrawGetSingleton - Gain access to a PetscDraw object as if it were owned
369         by the one process.
370 
371    Collective on PetscDraw
372 
373    Input Parameter:
374 .  draw - the original window
375 
376    Output Parameter:
377 .  sdraw - the singleton window
378 
379    Level: advanced
380 
381 .seealso: `PetscDrawRestoreSingleton()`, `PetscViewerGetSingleton()`, `PetscViewerRestoreSingleton()`
382 
383 @*/
384 PetscErrorCode PetscDrawGetSingleton(PetscDraw draw, PetscDraw *sdraw) {
385   PetscMPIInt size;
386 
387   PetscFunctionBegin;
388   PetscValidHeaderSpecific(draw, PETSC_DRAW_CLASSID, 1);
389   PetscValidPointer(sdraw, 2);
390 
391   PetscCallMPI(MPI_Comm_size(PetscObjectComm((PetscObject)draw), &size));
392   if (size == 1) {
393     PetscCall(PetscObjectReference((PetscObject)draw));
394     *sdraw = draw;
395   } else {
396     if (draw->ops->getsingleton) {
397       PetscUseTypeMethod(draw, getsingleton, sdraw);
398     } else SETERRQ(PETSC_COMM_SELF, PETSC_ERR_SUP, "Cannot get singleton for this type %s of draw object", ((PetscObject)draw)->type_name);
399   }
400   PetscFunctionReturn(0);
401 }
402 
403 /*@C
404    PetscDrawRestoreSingleton - Remove access to a PetscDraw object as if it were owned
405         by the one process.
406 
407    Collective on PetscDraw
408 
409    Input Parameters:
410 +  draw - the original window
411 -  sdraw - the singleton window
412 
413    Level: advanced
414 
415 .seealso: `PetscDrawGetSingleton()`, `PetscViewerGetSingleton()`, `PetscViewerRestoreSingleton()`
416 
417 @*/
418 PetscErrorCode PetscDrawRestoreSingleton(PetscDraw draw, PetscDraw *sdraw) {
419   PetscMPIInt size;
420 
421   PetscFunctionBegin;
422   PetscValidHeaderSpecific(draw, PETSC_DRAW_CLASSID, 1);
423   PetscValidPointer(sdraw, 2);
424   PetscValidHeaderSpecific(*sdraw, PETSC_DRAW_CLASSID, 2);
425 
426   PetscCallMPI(MPI_Comm_size(PetscObjectComm((PetscObject)draw), &size));
427   if (size == 1) {
428     if (draw == *sdraw) {
429       PetscCall(PetscObjectDereference((PetscObject)draw));
430       *sdraw = NULL;
431     } else SETERRQ(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Cannot restore singleton, it is not the parent draw");
432   } else PetscUseTypeMethod(draw, restoresingleton, sdraw);
433   PetscFunctionReturn(0);
434 }
435