Actual source code: drawv.c
1: #include <../src/sys/classes/viewer/impls/draw/vdraw.h>
2: #include <petscviewer.h>
4: static PetscErrorCode PetscViewerDestroy_Draw(PetscViewer v)
5: {
6: PetscInt i;
7: PetscViewer_Draw *vdraw = (PetscViewer_Draw *)v->data;
9: PetscFunctionBegin;
10: PetscCheck(!vdraw->singleton_made, PETSC_COMM_SELF, PETSC_ERR_ORDER, "Destroying PetscViewer without first restoring singleton");
11: for (i = 0; i < vdraw->draw_max; i++) {
12: PetscCall(PetscDrawAxisDestroy(&vdraw->drawaxis[i]));
13: PetscCall(PetscDrawLGDestroy(&vdraw->drawlg[i]));
14: PetscCall(PetscDrawDestroy(&vdraw->draw[i]));
15: }
16: PetscCall(PetscFree(vdraw->display));
17: PetscCall(PetscFree(vdraw->title));
18: PetscCall(PetscFree3(vdraw->draw, vdraw->drawlg, vdraw->drawaxis));
19: PetscCall(PetscFree(vdraw->bounds));
20: PetscCall(PetscFree(vdraw->drawtype));
21: PetscCall(PetscFree(v->data));
22: PetscFunctionReturn(PETSC_SUCCESS);
23: }
25: static PetscErrorCode PetscViewerFlush_Draw(PetscViewer v)
26: {
27: PetscInt i;
28: PetscViewer_Draw *vdraw = (PetscViewer_Draw *)v->data;
30: PetscFunctionBegin;
31: for (i = 0; i < vdraw->draw_max; i++) {
32: if (vdraw->draw[i]) PetscCall(PetscDrawFlush(vdraw->draw[i]));
33: }
34: PetscFunctionReturn(PETSC_SUCCESS);
35: }
37: /*@C
38: PetscViewerDrawGetDraw - Returns `PetscDraw` object from `PETSCVIEWERDRAW` `PetscViewer` object.
39: This `PetscDraw` object may then be used to perform graphics using `PetscDraw` commands.
41: Collective
43: Input Parameters:
44: + viewer - the `PetscViewer` (created with `PetscViewerDrawOpen()` of type `PETSCVIEWERDRAW`)
45: - windownumber - indicates which subwindow (usually 0) to obtain
47: Output Parameter:
48: . draw - the draw object
50: Level: intermediate
52: .seealso: [](sec_viewers), `PETSCVIEWERDRAW`, `PetscViewerDrawGetLG()`, `PetscViewerDrawGetAxis()`, `PetscViewerDrawOpen()`
53: @*/
54: PetscErrorCode PetscViewerDrawGetDraw(PetscViewer viewer, PetscInt windownumber, PetscDraw *draw)
55: {
56: PetscViewer_Draw *vdraw;
57: PetscBool isdraw;
59: PetscFunctionBegin;
62: if (draw) PetscAssertPointer(draw, 3);
63: PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERDRAW, &isdraw));
64: PetscCheck(isdraw, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Must be draw type PetscViewer");
65: PetscCheck(windownumber >= 0, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Window number cannot be negative");
66: vdraw = (PetscViewer_Draw *)viewer->data;
68: windownumber += vdraw->draw_base;
69: if (windownumber >= vdraw->draw_max) {
70: /* allocate twice as many slots as needed */
71: PetscInt draw_max = vdraw->draw_max;
72: PetscDraw *tdraw = vdraw->draw;
73: PetscDrawLG *drawlg = vdraw->drawlg;
74: PetscDrawAxis *drawaxis = vdraw->drawaxis;
76: vdraw->draw_max = 2 * windownumber;
78: PetscCall(PetscCalloc3(vdraw->draw_max, &vdraw->draw, vdraw->draw_max, &vdraw->drawlg, vdraw->draw_max, &vdraw->drawaxis));
79: PetscCall(PetscArraycpy(vdraw->draw, tdraw, draw_max));
80: PetscCall(PetscArraycpy(vdraw->drawlg, drawlg, draw_max));
81: PetscCall(PetscArraycpy(vdraw->drawaxis, drawaxis, draw_max));
82: PetscCall(PetscFree3(tdraw, drawlg, drawaxis));
83: }
85: if (!vdraw->draw[windownumber]) {
86: char *title = vdraw->title, tmp_str[128];
87: if (windownumber) {
88: PetscCall(PetscSNPrintf(tmp_str, sizeof(tmp_str), "%s:%" PetscInt_FMT, vdraw->title ? vdraw->title : "", windownumber));
89: title = tmp_str;
90: }
91: PetscCall(PetscDrawCreate(PetscObjectComm((PetscObject)viewer), vdraw->display, title, PETSC_DECIDE, PETSC_DECIDE, vdraw->w, vdraw->h, &vdraw->draw[windownumber]));
92: if (vdraw->drawtype) PetscCall(PetscDrawSetType(vdraw->draw[windownumber], vdraw->drawtype));
93: PetscCall(PetscDrawSetPause(vdraw->draw[windownumber], vdraw->pause));
94: PetscCall(PetscDrawSetOptionsPrefix(vdraw->draw[windownumber], ((PetscObject)viewer)->prefix));
95: PetscCall(PetscDrawSetFromOptions(vdraw->draw[windownumber]));
96: }
97: if (draw) *draw = vdraw->draw[windownumber];
99: PetscFunctionReturn(PETSC_SUCCESS);
100: }
102: /*@C
103: PetscViewerDrawBaseAdd - add to the base integer that is added to the `windownumber` passed to `PetscViewerDrawGetDraw()`
105: Logically Collective
107: Input Parameters:
108: + viewer - the `PetscViewer` (created with `PetscViewerDrawOpen()`)
109: - windownumber - how much to add to the base
111: Level: developer
113: Note:
114: A `PETSCVIEWERDRAW` may have multiple `PetscDraw` subwindows, this increases the number of the subwindow that is returned with `PetscViewerDrawGetDraw()`
116: .seealso: [](sec_viewers), `PetscViewerDrawGetLG()`, `PetscViewerDrawGetAxis()`, `PetscViewerDrawOpen()`, `PetscViewerDrawGetDraw()`, `PetscViewerDrawBaseSet()`
117: @*/
118: PetscErrorCode PetscViewerDrawBaseAdd(PetscViewer viewer, PetscInt windownumber)
119: {
120: PetscViewer_Draw *vdraw;
121: PetscBool isdraw;
123: PetscFunctionBegin;
126: PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERDRAW, &isdraw));
127: PetscCheck(isdraw, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Must be draw type PetscViewer");
128: vdraw = (PetscViewer_Draw *)viewer->data;
130: PetscCheck(windownumber + vdraw->draw_base >= 0, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Resulting base %" PetscInt_FMT " cannot be negative", windownumber + vdraw->draw_base);
131: vdraw->draw_base += windownumber;
132: PetscFunctionReturn(PETSC_SUCCESS);
133: }
135: /*@C
136: PetscViewerDrawBaseSet - sets the base integer that is added to the `windownumber` passed to `PetscViewerDrawGetDraw()`
138: Logically Collective
140: Input Parameters:
141: + viewer - the `PetscViewer` (created with `PetscViewerDrawOpen()`)
142: - windownumber - value to set the base
144: Level: developer
146: Note:
147: A `PETSCVIEWERDRAW` may have multiple `PetscDraw` subwindows, this increases the number of the subwindow that is returned with `PetscViewerDrawGetDraw()`
149: .seealso: [](sec_viewers), `PetscViewerDrawGetLG()`, `PetscViewerDrawGetAxis()`, `PetscViewerDrawOpen()`, `PetscViewerDrawGetDraw()`, `PetscViewerDrawBaseAdd()`
150: @*/
151: PetscErrorCode PetscViewerDrawBaseSet(PetscViewer viewer, PetscInt windownumber)
152: {
153: PetscViewer_Draw *vdraw;
154: PetscBool isdraw;
156: PetscFunctionBegin;
159: PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERDRAW, &isdraw));
160: PetscCheck(isdraw, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Must be draw type PetscViewer");
161: vdraw = (PetscViewer_Draw *)viewer->data;
163: PetscCheck(windownumber >= 0, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Resulting base %" PetscInt_FMT " cannot be negative", windownumber);
164: vdraw->draw_base = windownumber;
165: PetscFunctionReturn(PETSC_SUCCESS);
166: }
168: /*@C
169: PetscViewerDrawGetDrawLG - Returns a `PetscDrawLG` object from `PetscViewer` object of type `PETSCVIEWERDRAW`.
170: This `PetscDrawLG` object may then be used to perform graphics using `PetscDrawLG` commands.
172: Collective
174: Input Parameters:
175: + viewer - the `PetscViewer` (created with `PetscViewerDrawOpen()`)
176: - windownumber - indicates which subwindow (usually 0)
178: Output Parameter:
179: . drawlg - the draw line graph object
181: Level: intermediate
183: Note:
184: A `PETSCVIEWERDRAW` may have multiple `PetscDraw` subwindows
186: .seealso: [](sec_viewers), `PetscDrawLG`, `PetscViewerDrawGetDraw()`, `PetscViewerDrawGetAxis()`, `PetscViewerDrawOpen()`
187: @*/
188: PetscErrorCode PetscViewerDrawGetDrawLG(PetscViewer viewer, PetscInt windownumber, PetscDrawLG *drawlg)
189: {
190: PetscBool isdraw;
191: PetscViewer_Draw *vdraw;
193: PetscFunctionBegin;
196: PetscAssertPointer(drawlg, 3);
197: PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERDRAW, &isdraw));
198: PetscCheck(isdraw, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Must be draw type PetscViewer");
199: PetscCheck(windownumber >= 0, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Window number cannot be negative");
200: vdraw = (PetscViewer_Draw *)viewer->data;
202: if (windownumber + vdraw->draw_base >= vdraw->draw_max || !vdraw->draw[windownumber + vdraw->draw_base]) PetscCall(PetscViewerDrawGetDraw(viewer, windownumber, NULL));
203: if (!vdraw->drawlg[windownumber + vdraw->draw_base]) {
204: PetscCall(PetscDrawLGCreate(vdraw->draw[windownumber + vdraw->draw_base], 1, &vdraw->drawlg[windownumber + vdraw->draw_base]));
205: PetscCall(PetscDrawLGSetFromOptions(vdraw->drawlg[windownumber + vdraw->draw_base]));
206: }
207: *drawlg = vdraw->drawlg[windownumber + vdraw->draw_base];
208: PetscFunctionReturn(PETSC_SUCCESS);
209: }
211: /*@C
212: PetscViewerDrawGetDrawAxis - Returns a `PetscDrawAxis` object from a `PetscViewer` object of type `PETSCVIEWERDRAW`.
213: This `PetscDrawAxis` object may then be used to perform graphics using `PetscDrawAxis` commands.
215: Collective
217: Input Parameters:
218: + viewer - the `PetscViewer` (created with `PetscViewerDrawOpen()`)
219: - windownumber - indicates which subwindow (usually 0)
221: Output Parameter:
222: . drawaxis - the draw axis object
224: Level: advanced
226: Note:
227: A `PETSCVIEWERDRAW` may have multiple `PetscDraw` subwindows
229: .seealso: [](sec_viewers), `PetscViewerDrawGetDraw()`, `PetscViewerDrawGetLG()`, `PetscViewerDrawOpen()`
230: @*/
231: PetscErrorCode PetscViewerDrawGetDrawAxis(PetscViewer viewer, PetscInt windownumber, PetscDrawAxis *drawaxis)
232: {
233: PetscBool isdraw;
234: PetscViewer_Draw *vdraw;
236: PetscFunctionBegin;
239: PetscAssertPointer(drawaxis, 3);
240: PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERDRAW, &isdraw));
241: PetscCheck(isdraw, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Must be draw type PetscViewer");
242: PetscCheck(windownumber >= 0, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Window number cannot be negative");
243: vdraw = (PetscViewer_Draw *)viewer->data;
245: if (windownumber + vdraw->draw_base >= vdraw->draw_max || !vdraw->draw[windownumber + vdraw->draw_base]) PetscCall(PetscViewerDrawGetDraw(viewer, windownumber, NULL));
246: if (!vdraw->drawaxis[windownumber + vdraw->draw_base]) PetscCall(PetscDrawAxisCreate(vdraw->draw[windownumber + vdraw->draw_base], &vdraw->drawaxis[windownumber + vdraw->draw_base]));
247: *drawaxis = vdraw->drawaxis[windownumber + vdraw->draw_base];
248: PetscFunctionReturn(PETSC_SUCCESS);
249: }
251: PetscErrorCode PetscViewerDrawResize(PetscViewer v, int w, int h)
252: {
253: PetscViewer_Draw *vdraw;
254: PetscBool isdraw;
256: PetscFunctionBegin;
258: PetscCall(PetscObjectTypeCompare((PetscObject)v, PETSCVIEWERDRAW, &isdraw));
259: if (!isdraw) PetscFunctionReturn(PETSC_SUCCESS);
260: vdraw = (PetscViewer_Draw *)v->data;
262: if (w >= 1) vdraw->w = w;
263: if (h >= 1) vdraw->h = h;
264: PetscFunctionReturn(PETSC_SUCCESS);
265: }
267: PetscErrorCode PetscViewerDrawSetInfo(PetscViewer v, const char display[], const char title[], int x, int y, int w, int h)
268: {
269: PetscViewer_Draw *vdraw;
270: PetscBool isdraw;
272: PetscFunctionBegin;
274: PetscCall(PetscObjectTypeCompare((PetscObject)v, PETSCVIEWERDRAW, &isdraw));
275: if (!isdraw) PetscFunctionReturn(PETSC_SUCCESS);
276: vdraw = (PetscViewer_Draw *)v->data;
278: PetscCall(PetscStrallocpy(display, &vdraw->display));
279: PetscCall(PetscStrallocpy(title, &vdraw->title));
280: if (w >= 1) vdraw->w = w;
281: if (h >= 1) vdraw->h = h;
282: PetscFunctionReturn(PETSC_SUCCESS);
283: }
285: PetscErrorCode PetscViewerDrawSetDrawType(PetscViewer v, PetscDrawType drawtype)
286: {
287: PetscViewer_Draw *vdraw;
288: PetscBool isdraw;
290: PetscFunctionBegin;
292: PetscCall(PetscObjectTypeCompare((PetscObject)v, PETSCVIEWERDRAW, &isdraw));
293: if (!isdraw) PetscFunctionReturn(PETSC_SUCCESS);
294: vdraw = (PetscViewer_Draw *)v->data;
296: PetscCall(PetscFree(vdraw->drawtype));
297: PetscCall(PetscStrallocpy(drawtype, (char **)&vdraw->drawtype));
298: PetscFunctionReturn(PETSC_SUCCESS);
299: }
301: PetscErrorCode PetscViewerDrawGetDrawType(PetscViewer v, PetscDrawType *drawtype)
302: {
303: PetscViewer_Draw *vdraw;
304: PetscBool isdraw;
306: PetscFunctionBegin;
308: PetscCall(PetscObjectTypeCompare((PetscObject)v, PETSCVIEWERDRAW, &isdraw));
309: PetscCheck(isdraw, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Must be draw type PetscViewer");
310: vdraw = (PetscViewer_Draw *)v->data;
312: *drawtype = vdraw->drawtype;
313: PetscFunctionReturn(PETSC_SUCCESS);
314: }
316: PetscErrorCode PetscViewerDrawSetTitle(PetscViewer v, const char title[])
317: {
318: PetscViewer_Draw *vdraw;
319: PetscBool isdraw;
321: PetscFunctionBegin;
323: PetscCall(PetscObjectTypeCompare((PetscObject)v, PETSCVIEWERDRAW, &isdraw));
324: if (!isdraw) PetscFunctionReturn(PETSC_SUCCESS);
325: vdraw = (PetscViewer_Draw *)v->data;
327: PetscCall(PetscFree(vdraw->title));
328: PetscCall(PetscStrallocpy(title, &vdraw->title));
329: PetscFunctionReturn(PETSC_SUCCESS);
330: }
332: PetscErrorCode PetscViewerDrawGetTitle(PetscViewer v, const char *title[])
333: {
334: PetscViewer_Draw *vdraw;
335: PetscBool isdraw;
337: PetscFunctionBegin;
339: PetscCall(PetscObjectTypeCompare((PetscObject)v, PETSCVIEWERDRAW, &isdraw));
340: PetscCheck(isdraw, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Must be draw type PetscViewer");
341: vdraw = (PetscViewer_Draw *)v->data;
343: *title = vdraw->title;
344: PetscFunctionReturn(PETSC_SUCCESS);
345: }
347: /*@C
348: PetscViewerDrawOpen - Opens a `PetscDraw` window for use as a `PetscViewer` with type
349: `PETSCVIEWERDRAW`.
351: Collective
353: Input Parameters:
354: + comm - communicator that will share window
355: . display - the X display on which to open, or `NULL` for the local machine
356: . title - the title to put in the title bar, or `NULL` for no title
357: . x - horizontal screen coordinate of the upper left corner of window, or use `PETSC_DECIDE`
358: . y - vertical screen coordinate of the upper left corner of window, or use `PETSC_DECIDE`
359: . w - window width in pixels, or may use `PETSC_DECIDE` or `PETSC_DRAW_FULL_SIZE`, `PETSC_DRAW_HALF_SIZE`,`PETSC_DRAW_THIRD_SIZE`, `PETSC_DRAW_QUARTER_SIZE`
360: - h - window height in pixels, or may use `PETSC_DECIDE` or `PETSC_DRAW_FULL_SIZE`, `PETSC_DRAW_HALF_SIZE`,`PETSC_DRAW_THIRD_SIZE`, `PETSC_DRAW_QUARTER_SIZE`
362: Output Parameter:
363: . viewer - the `PetscViewer`
365: Options Database Keys:
366: + -draw_type - use x or null
367: . -nox - Disables all x-windows output
368: . -display <name> - Specifies name of machine for the X display
369: . -geometry <x,y,w,h> - allows setting the window location and size
370: - -draw_pause <pause> - Sets time (in seconds) that the
371: program pauses after PetscDrawPause() has been called
372: (0 is default, -1 implies until user input).
374: Level: beginner
376: Notes:
377: If you want to do graphics in this window, you must call `PetscViewerDrawGetDraw()` and
378: perform the graphics on the `PetscDraw` object.
380: Format options include\:
381: + `PETSC_VIEWER_DRAW_BASIC` - displays with basic format
382: - `PETSC_VIEWER_DRAW_LG` - displays using a line graph
384: Fortran Notes:
385: Whenever indicating null character data in a Fortran code,
386: `PETSC_NULL_CHARACTER` must be employed; using NULL is not
387: correct for character data! Thus, `PETSC_NULL_CHARACTER` can be
388: used for the display and title input parameters.
390: .seealso: [](sec_viewers), `PETSCVIEWERDRAW`, `PetscDrawCreate()`, `PetscViewerDestroy()`, `PetscViewerDrawGetDraw()`, `PetscViewerCreate()`, `PETSC_VIEWER_DRAW_`,
391: `PETSC_VIEWER_DRAW_WORLD`, `PETSC_VIEWER_DRAW_SELF`
392: @*/
393: PetscErrorCode PetscViewerDrawOpen(MPI_Comm comm, const char display[], const char title[], int x, int y, int w, int h, PetscViewer *viewer)
394: {
395: PetscFunctionBegin;
396: PetscCall(PetscViewerCreate(comm, viewer));
397: PetscCall(PetscViewerSetType(*viewer, PETSCVIEWERDRAW));
398: PetscCall(PetscViewerDrawSetInfo(*viewer, display, title, x, y, w, h));
399: PetscFunctionReturn(PETSC_SUCCESS);
400: }
402: #include <petsc/private/drawimpl.h>
404: static PetscErrorCode PetscViewerGetSubViewer_Draw(PetscViewer viewer, MPI_Comm comm, PetscViewer *sviewer)
405: {
406: PetscMPIInt rank;
407: PetscInt i;
408: PetscViewer_Draw *vdraw = (PetscViewer_Draw *)viewer->data, *svdraw;
410: PetscFunctionBegin;
411: PetscCheck(!vdraw->singleton_made, PETSC_COMM_SELF, PETSC_ERR_ORDER, "Trying to get SubViewer without first restoring previous");
412: /* only processor zero can use the PetscViewer draw singleton */
413: if (sviewer) *sviewer = NULL;
414: PetscCallMPI(MPI_Comm_rank(PetscObjectComm((PetscObject)viewer), &rank));
415: if (rank == 0) {
416: PetscMPIInt flg;
417: PetscDraw draw, sdraw;
419: PetscCallMPI(MPI_Comm_compare(PETSC_COMM_SELF, comm, &flg));
420: PetscCheck(flg == MPI_IDENT || flg == MPI_CONGRUENT, PETSC_COMM_SELF, PETSC_ERR_SUP, "PetscViewerGetSubViewer() for PETSCVIEWERDRAW requires a singleton MPI_Comm");
421: PetscCall(PetscViewerCreate(comm, sviewer));
422: PetscCall(PetscViewerSetType(*sviewer, PETSCVIEWERDRAW));
423: svdraw = (PetscViewer_Draw *)(*sviewer)->data;
424: (*sviewer)->format = viewer->format;
425: for (i = 0; i < vdraw->draw_max; i++) { /* XXX this is wrong if svdraw->draw_max (initially 5) < vdraw->draw_max */
426: if (vdraw->draw[i]) PetscCall(PetscDrawGetSingleton(vdraw->draw[i], &svdraw->draw[i]));
427: }
428: PetscCall(PetscViewerDrawGetDraw(viewer, 0, &draw));
429: PetscCall(PetscViewerDrawGetDraw(*sviewer, 0, &sdraw));
430: if (draw->savefilename) {
431: PetscCall(PetscDrawSetSave(sdraw, draw->savefilename));
432: sdraw->savefilecount = draw->savefilecount;
433: sdraw->savesinglefile = draw->savesinglefile;
434: sdraw->savemoviefps = draw->savemoviefps;
435: sdraw->saveonclear = draw->saveonclear;
436: sdraw->saveonflush = draw->saveonflush;
437: }
438: if (draw->savefinalfilename) PetscCall(PetscDrawSetSaveFinalImage(sdraw, draw->savefinalfilename));
439: } else {
440: PetscDraw draw;
441: PetscCall(PetscViewerDrawGetDraw(viewer, 0, &draw));
442: }
443: vdraw->singleton_made = PETSC_TRUE;
444: PetscFunctionReturn(PETSC_SUCCESS);
445: }
447: static PetscErrorCode PetscViewerRestoreSubViewer_Draw(PetscViewer viewer, MPI_Comm comm, PetscViewer *sviewer)
448: {
449: PetscMPIInt rank;
450: PetscInt i;
451: PetscViewer_Draw *vdraw = (PetscViewer_Draw *)viewer->data, *svdraw;
453: PetscFunctionBegin;
454: PetscCheck(vdraw->singleton_made, PETSC_COMM_SELF, PETSC_ERR_ORDER, "Trying to restore a singleton that was not gotten");
455: PetscCallMPI(MPI_Comm_rank(PetscObjectComm((PetscObject)viewer), &rank));
456: if (rank == 0) {
457: PetscDraw draw, sdraw;
459: PetscCall(PetscViewerDrawGetDraw(viewer, 0, &draw));
460: PetscCall(PetscViewerDrawGetDraw(*sviewer, 0, &sdraw));
461: if (draw->savefilename) {
462: draw->savefilecount = sdraw->savefilecount;
463: PetscCallMPI(MPI_Bcast(&draw->savefilecount, 1, MPIU_INT, 0, PetscObjectComm((PetscObject)draw)));
464: }
465: svdraw = (PetscViewer_Draw *)(*sviewer)->data;
466: for (i = 0; i < vdraw->draw_max; i++) {
467: if (vdraw->draw[i] && svdraw->draw[i]) PetscCall(PetscDrawRestoreSingleton(vdraw->draw[i], &svdraw->draw[i]));
468: }
469: PetscCall(PetscFree3(svdraw->draw, svdraw->drawlg, svdraw->drawaxis));
470: PetscCall(PetscFree((*sviewer)->data));
471: PetscCall(PetscHeaderDestroy(sviewer));
472: } else {
473: PetscDraw draw;
475: PetscCall(PetscViewerDrawGetDraw(viewer, 0, &draw));
476: if (draw->savefilename) PetscCallMPI(MPI_Bcast(&draw->savefilecount, 1, MPIU_INT, 0, PetscObjectComm((PetscObject)draw)));
477: }
479: vdraw->singleton_made = PETSC_FALSE;
480: PetscFunctionReturn(PETSC_SUCCESS);
481: }
483: static PetscErrorCode PetscViewerSetFromOptions_Draw(PetscViewer v, PetscOptionItems *PetscOptionsObject)
484: {
485: PetscReal bounds[16];
486: PetscInt nbounds = 16;
487: PetscBool flg;
489: PetscFunctionBegin;
490: PetscOptionsHeadBegin(PetscOptionsObject, "Draw PetscViewer Options");
491: PetscCall(PetscOptionsRealArray("-draw_bounds", "Bounds to put on plots axis", "PetscViewerDrawSetBounds", bounds, &nbounds, &flg));
492: if (flg) PetscCall(PetscViewerDrawSetBounds(v, nbounds / 2, bounds));
493: PetscOptionsHeadEnd();
494: PetscFunctionReturn(PETSC_SUCCESS);
495: }
497: static PetscErrorCode PetscViewerView_Draw(PetscViewer viewer, PetscViewer v)
498: {
499: PetscDraw draw;
500: PetscInt i;
501: PetscViewer_Draw *vdraw = (PetscViewer_Draw *)viewer->data;
502: PetscBool iascii;
504: PetscFunctionBegin;
505: PetscCall(PetscObjectTypeCompare((PetscObject)v, PETSCVIEWERASCII, &iascii));
506: if (iascii) PetscCall(PetscViewerASCIIPrintf(v, "Draw viewer is of type %s\n", vdraw->drawtype));
507: /* If the PetscViewer has just been created then no vdraw->draw yet
508: exists so this will not actually call the viewer on any draws. */
509: for (i = 0; i < vdraw->draw_base; i++) {
510: if (vdraw->draw[i]) {
511: PetscCall(PetscViewerDrawGetDraw(viewer, i, &draw));
512: PetscCall(PetscDrawView(draw, v));
513: }
514: }
515: PetscFunctionReturn(PETSC_SUCCESS);
516: }
518: /*MC
519: PETSCVIEWERDRAW - A viewer that generates graphics, either to the screen or a file
521: Level: beginner
523: .seealso: [](sec_viewers), `PetscViewerDrawOpen()`, `PetscViewerDrawGetDraw()`, `PETSC_VIEWER_DRAW_()`, `PETSC_VIEWER_DRAW_SELF`, `PETSC_VIEWER_DRAW_WORLD`,
524: `PetscViewerCreate()`, `PetscViewerASCIIOpen()`, `PetscViewerBinaryOpen()`, `PETSCVIEWERBINARY`,
525: `PetscViewerMatlabOpen()`, `VecView()`, `DMView()`, `PetscViewerMatlabPutArray()`, `PETSCVIEWERASCII`, `PETSCVIEWERMATLAB`,
526: `PetscViewerFileSetName()`, `PetscViewerFileSetMode()`, `PetscViewerFormat`, `PetscViewerType`, `PetscViewerSetType()`
527: M*/
528: PETSC_EXTERN PetscErrorCode PetscViewerCreate_Draw(PetscViewer viewer)
529: {
530: PetscViewer_Draw *vdraw;
532: PetscFunctionBegin;
533: PetscCall(PetscNew(&vdraw));
534: viewer->data = (void *)vdraw;
536: viewer->ops->flush = PetscViewerFlush_Draw;
537: viewer->ops->view = PetscViewerView_Draw;
538: viewer->ops->destroy = PetscViewerDestroy_Draw;
539: viewer->ops->setfromoptions = PetscViewerSetFromOptions_Draw;
540: viewer->ops->getsubviewer = PetscViewerGetSubViewer_Draw;
541: viewer->ops->restoresubviewer = PetscViewerRestoreSubViewer_Draw;
543: /* these are created on the fly if requested */
544: vdraw->draw_max = 5;
545: vdraw->draw_base = 0;
546: vdraw->w = PETSC_DECIDE;
547: vdraw->h = PETSC_DECIDE;
549: PetscCall(PetscCalloc3(vdraw->draw_max, &vdraw->draw, vdraw->draw_max, &vdraw->drawlg, vdraw->draw_max, &vdraw->drawaxis));
550: vdraw->singleton_made = PETSC_FALSE;
551: PetscFunctionReturn(PETSC_SUCCESS);
552: }
554: /*@
555: PetscViewerDrawClear - Clears a `PetscDraw` graphic associated with a `PetscViewer`.
557: Not Collective
559: Input Parameter:
560: . viewer - the `PetscViewer`
562: Level: intermediate
564: .seealso: [](sec_viewers), `PETSCVIEWERDRAW`, `PetscViewerDrawOpen()`, `PetscViewerDrawGetDraw()`,
565: @*/
566: PetscErrorCode PetscViewerDrawClear(PetscViewer viewer)
567: {
568: PetscViewer_Draw *vdraw;
569: PetscBool isdraw;
570: PetscInt i;
572: PetscFunctionBegin;
574: PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERDRAW, &isdraw));
575: if (!isdraw) PetscFunctionReturn(PETSC_SUCCESS);
576: vdraw = (PetscViewer_Draw *)viewer->data;
578: for (i = 0; i < vdraw->draw_max; i++) {
579: if (vdraw->draw[i]) PetscCall(PetscDrawClear(vdraw->draw[i]));
580: }
581: PetscFunctionReturn(PETSC_SUCCESS);
582: }
584: /*@
585: PetscViewerDrawGetPause - Gets the pause value (how long to pause before an image is changed) in the `PETSCVIEWERDRAW` `PetscViewer`
587: Not Collective
589: Input Parameter:
590: . viewer - the `PetscViewer`
592: Output Parameter:
593: . pause - the pause value
595: Level: intermediate
597: .seealso: [](sec_viewers), `PETSCVIEWERDRAW`, `PetscViewerDrawOpen()`, `PetscViewerDrawGetDraw()`,
598: @*/
599: PetscErrorCode PetscViewerDrawGetPause(PetscViewer viewer, PetscReal *pause)
600: {
601: PetscViewer_Draw *vdraw;
602: PetscBool isdraw;
603: PetscInt i;
604: PetscDraw draw;
606: PetscFunctionBegin;
608: PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERDRAW, &isdraw));
609: if (!isdraw) {
610: *pause = 0.0;
611: PetscFunctionReturn(PETSC_SUCCESS);
612: }
613: vdraw = (PetscViewer_Draw *)viewer->data;
615: for (i = 0; i < vdraw->draw_max; i++) {
616: if (vdraw->draw[i]) {
617: PetscCall(PetscDrawGetPause(vdraw->draw[i], pause));
618: PetscFunctionReturn(PETSC_SUCCESS);
619: }
620: }
621: /* none exist yet so create one and get its pause */
622: PetscCall(PetscViewerDrawGetDraw(viewer, 0, &draw));
623: PetscCall(PetscDrawGetPause(draw, pause));
624: PetscFunctionReturn(PETSC_SUCCESS);
625: }
627: /*@
628: PetscViewerDrawSetPause - Sets a pause for each `PetscDraw` in the `PETSCVIEWERDRAW` `PetscViewer`
630: Not Collective
632: Input Parameters:
633: + viewer - the `PetscViewer`
634: - pause - the pause value
636: Level: intermediate
638: .seealso: [](sec_viewers), `PETSCVIEWERDRAW`, `PetscViewerDrawOpen()`, `PetscViewerDrawGetDraw()`,
639: @*/
640: PetscErrorCode PetscViewerDrawSetPause(PetscViewer viewer, PetscReal pause)
641: {
642: PetscViewer_Draw *vdraw;
643: PetscBool isdraw;
644: PetscInt i;
646: PetscFunctionBegin;
648: PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERDRAW, &isdraw));
649: if (!isdraw) PetscFunctionReturn(PETSC_SUCCESS);
650: vdraw = (PetscViewer_Draw *)viewer->data;
652: vdraw->pause = pause;
653: for (i = 0; i < vdraw->draw_max; i++) {
654: if (vdraw->draw[i]) PetscCall(PetscDrawSetPause(vdraw->draw[i], pause));
655: }
656: PetscFunctionReturn(PETSC_SUCCESS);
657: }
659: /*@
660: PetscViewerDrawSetHold - Holds previous image when drawing new image in a `PETSCVIEWERDRAW`
662: Not Collective
664: Input Parameters:
665: + viewer - the `PetscViewer`
666: - hold - `PETSC_TRUE` indicates to hold the previous image
668: Level: intermediate
670: .seealso: [](sec_viewers), `PETSCVIEWERDRAW`, `PetscViewerDrawOpen()`, `PetscViewerDrawGetDraw()`,
671: @*/
672: PetscErrorCode PetscViewerDrawSetHold(PetscViewer viewer, PetscBool hold)
673: {
674: PetscViewer_Draw *vdraw;
675: PetscBool isdraw;
677: PetscFunctionBegin;
679: PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERDRAW, &isdraw));
680: if (!isdraw) PetscFunctionReturn(PETSC_SUCCESS);
681: vdraw = (PetscViewer_Draw *)viewer->data;
683: vdraw->hold = hold;
684: PetscFunctionReturn(PETSC_SUCCESS);
685: }
687: /*@
688: PetscViewerDrawGetHold - Checks if the `PETSCVIEWERDRAW` `PetscViewer` holds previous image when drawing new image
690: Not Collective
692: Input Parameter:
693: . viewer - the `PetscViewer`
695: Output Parameter:
696: . hold - indicates to hold or not
698: Level: intermediate
700: .seealso: [](sec_viewers), `PETSCVIEWERDRAW`, `PetscViewerDrawOpen()`, `PetscViewerDrawGetDraw()`,
701: @*/
702: PetscErrorCode PetscViewerDrawGetHold(PetscViewer viewer, PetscBool *hold)
703: {
704: PetscViewer_Draw *vdraw;
705: PetscBool isdraw;
707: PetscFunctionBegin;
709: PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERDRAW, &isdraw));
710: if (!isdraw) {
711: *hold = PETSC_FALSE;
712: PetscFunctionReturn(PETSC_SUCCESS);
713: }
714: vdraw = (PetscViewer_Draw *)viewer->data;
716: *hold = vdraw->hold;
717: PetscFunctionReturn(PETSC_SUCCESS);
718: }
720: /*
721: The variable Petsc_Viewer_Draw_keyval is used to indicate an MPI attribute that
722: is attached to a communicator, in this case the attribute is a PetscViewer.
723: */
724: PetscMPIInt Petsc_Viewer_Draw_keyval = MPI_KEYVAL_INVALID;
726: /*@C
727: PETSC_VIEWER_DRAW_ - Creates a window `PETSCVIEWERDRAW` `PetscViewer` shared by all processors
728: in an MPI communicator.
730: Collective
732: Input Parameter:
733: . comm - the MPI communicator to share the window `PetscViewer`
735: Level: intermediate
737: Notes:
738: This object is destroyed in `PetscFinalize()`, `PetscViewerDestroy()` should never be called on it
740: Unlike almost all other PETSc routines, `PETSC_VIEWER_DRAW_()` does not return
741: an error code. The window is usually used in the form
742: $ XXXView(XXX object, PETSC_VIEWER_DRAW_(comm));
744: .seealso: [](sec_viewers), `PETSCVIEWERDRAW`, `PetscViewer`, `PETSC_VIEWER_DRAW_WORLD`, `PETSC_VIEWER_DRAW_SELF`, `PetscViewerDrawOpen()`,
745: @*/
746: PetscViewer PETSC_VIEWER_DRAW_(MPI_Comm comm)
747: {
748: PetscErrorCode ierr;
749: PetscMPIInt flag, mpi_ierr;
750: PetscViewer viewer;
751: MPI_Comm ncomm;
753: PetscFunctionBegin;
754: ierr = PetscCommDuplicate(comm, &ncomm, NULL);
755: if (ierr) {
756: ierr = PetscError(PETSC_COMM_SELF, __LINE__, "PETSC_VIEWER_DRAW_", __FILE__, PETSC_ERR_PLIB, PETSC_ERROR_INITIAL, " ");
757: PetscFunctionReturn(NULL);
758: }
759: if (Petsc_Viewer_Draw_keyval == MPI_KEYVAL_INVALID) {
760: mpi_ierr = MPI_Comm_create_keyval(MPI_COMM_NULL_COPY_FN, MPI_COMM_NULL_DELETE_FN, &Petsc_Viewer_Draw_keyval, NULL);
761: if (mpi_ierr) {
762: ierr = PetscError(PETSC_COMM_SELF, __LINE__, "PETSC_VIEWER_DRAW_", __FILE__, PETSC_ERR_PLIB, PETSC_ERROR_INITIAL, " ");
763: PetscFunctionReturn(NULL);
764: }
765: }
766: mpi_ierr = MPI_Comm_get_attr(ncomm, Petsc_Viewer_Draw_keyval, (void **)&viewer, &flag);
767: if (mpi_ierr) {
768: ierr = PetscError(PETSC_COMM_SELF, __LINE__, "PETSC_VIEWER_DRAW_", __FILE__, PETSC_ERR_PLIB, PETSC_ERROR_INITIAL, " ");
769: PetscFunctionReturn(NULL);
770: }
771: if (!flag) { /* PetscViewer not yet created */
772: ierr = PetscViewerDrawOpen(ncomm, NULL, NULL, PETSC_DECIDE, PETSC_DECIDE, 300, 300, &viewer);
773: ((PetscObject)viewer)->persistent = PETSC_TRUE;
774: if (ierr) {
775: ierr = PetscError(PETSC_COMM_SELF, __LINE__, "PETSC_VIEWER_DRAW_", __FILE__, PETSC_ERR_PLIB, PETSC_ERROR_REPEAT, " ");
776: PetscFunctionReturn(NULL);
777: }
778: ierr = PetscObjectRegisterDestroy((PetscObject)viewer);
779: if (ierr) {
780: ierr = PetscError(PETSC_COMM_SELF, __LINE__, "PETSC_VIEWER_DRAW_", __FILE__, PETSC_ERR_PLIB, PETSC_ERROR_REPEAT, " ");
781: PetscFunctionReturn(NULL);
782: }
783: mpi_ierr = MPI_Comm_set_attr(ncomm, Petsc_Viewer_Draw_keyval, (void *)viewer);
784: if (mpi_ierr) {
785: ierr = PetscError(PETSC_COMM_SELF, __LINE__, "PETSC_VIEWER_DRAW_", __FILE__, PETSC_ERR_PLIB, PETSC_ERROR_INITIAL, " ");
786: PetscFunctionReturn(NULL);
787: }
788: }
789: ierr = PetscCommDestroy(&ncomm);
790: if (ierr) {
791: ierr = PetscError(PETSC_COMM_SELF, __LINE__, "PETSC_VIEWER_DRAW_", __FILE__, PETSC_ERR_PLIB, PETSC_ERROR_REPEAT, " ");
792: PetscFunctionReturn(NULL);
793: }
794: PetscFunctionReturn(viewer);
795: }
797: /*@
798: PetscViewerDrawSetBounds - sets the upper and lower bounds to be used in plotting in a `PETSCVIEWERDRAW` `PetscViewer`
800: Collective
802: Input Parameters:
803: + viewer - the Petsc`Viewer` (created with `PetscViewerDrawOpen()`)
804: . nbounds - number of plots that can be made with this viewer, for example the dof passed to `DMDACreate()`
805: - bounds - the actual bounds, the size of this is 2*`nbounds`, the values are stored in the order min F_0, max F_0, min F_1, max F_1, .....
807: Options Database Key:
808: . -draw_bounds minF0,maxF0,minF1,maxF1 - the lower left and upper right bounds
810: Level: intermediate
812: Note:
813: this determines the colors used in 2d contour plots generated with VecView() for `DMDA` in 2d. Any values in the vector below or above the
814: bounds are moved to the bound value before plotting. In this way the color index from color to physical value remains the same for all plots generated with
815: this viewer. Otherwise the color to physical value meaning changes with each new image if this is not set.
817: .seealso: [](sec_viewers), `PETSCVIEWERDRAW`, `PetscViewerDrawGetLG()`, `PetscViewerDrawGetAxis()`, `PetscViewerDrawOpen()`
818: @*/
819: PetscErrorCode PetscViewerDrawSetBounds(PetscViewer viewer, PetscInt nbounds, const PetscReal *bounds)
820: {
821: PetscViewer_Draw *vdraw;
822: PetscBool isdraw;
824: PetscFunctionBegin;
826: PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERDRAW, &isdraw));
827: if (!isdraw) PetscFunctionReturn(PETSC_SUCCESS);
828: vdraw = (PetscViewer_Draw *)viewer->data;
830: vdraw->nbounds = nbounds;
831: PetscCall(PetscFree(vdraw->bounds));
832: PetscCall(PetscMalloc1(2 * nbounds, &vdraw->bounds));
833: PetscCall(PetscArraycpy(vdraw->bounds, bounds, 2 * nbounds));
834: PetscFunctionReturn(PETSC_SUCCESS);
835: }
837: /*@C
838: PetscViewerDrawGetBounds - gets the upper and lower bounds to be used in plotting set with `PetscViewerDrawSetBounds()`
840: Collective
842: Input Parameter:
843: . viewer - the `PetscViewer` (created with `PetscViewerDrawOpen()`)
845: Output Parameters:
846: + nbounds - number of plots that can be made with this viewer, for example the dof passed to `DMDACreate()`
847: - bounds - the actual bounds, the size of this is 2*`nbounds`, the values are stored in the order min F_0, max F_0, min F_1, max F_1, .....
849: Level: intermediate
851: .seealso: [](sec_viewers), `PETSCVIEWERDRAW`, `PetscViewerDrawGetLG()`, `PetscViewerDrawGetAxis()`, `PetscViewerDrawOpen()`, `PetscViewerDrawSetBounds()`
852: @*/
853: PetscErrorCode PetscViewerDrawGetBounds(PetscViewer viewer, PetscInt *nbounds, const PetscReal **bounds)
854: {
855: PetscViewer_Draw *vdraw;
856: PetscBool isdraw;
858: PetscFunctionBegin;
860: PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERDRAW, &isdraw));
861: if (!isdraw) {
862: if (nbounds) *nbounds = 0;
863: if (bounds) *bounds = NULL;
864: PetscFunctionReturn(PETSC_SUCCESS);
865: }
866: vdraw = (PetscViewer_Draw *)viewer->data;
868: if (nbounds) *nbounds = vdraw->nbounds;
869: if (bounds) *bounds = vdraw->bounds;
870: PetscFunctionReturn(PETSC_SUCCESS);
871: }