Actual source code: drawv.c
2: #include <../src/sys/classes/viewer/impls/draw/vdraw.h>
3: #include <petscviewer.h>
5: static PetscErrorCode PetscViewerDestroy_Draw(PetscViewer v)
6: {
7: PetscInt i;
8: PetscViewer_Draw *vdraw = (PetscViewer_Draw *)v->data;
10: PetscFunctionBegin;
11: PetscCheck(!vdraw->singleton_made, PETSC_COMM_SELF, PETSC_ERR_ORDER, "Destroying PetscViewer without first restoring singleton");
12: for (i = 0; i < vdraw->draw_max; i++) {
13: PetscCall(PetscDrawAxisDestroy(&vdraw->drawaxis[i]));
14: PetscCall(PetscDrawLGDestroy(&vdraw->drawlg[i]));
15: PetscCall(PetscDrawDestroy(&vdraw->draw[i]));
16: }
17: PetscCall(PetscFree(vdraw->display));
18: PetscCall(PetscFree(vdraw->title));
19: PetscCall(PetscFree3(vdraw->draw, vdraw->drawlg, vdraw->drawaxis));
20: PetscCall(PetscFree(vdraw->bounds));
21: PetscCall(PetscFree(vdraw->drawtype));
22: PetscCall(PetscFree(v->data));
23: PetscFunctionReturn(PETSC_SUCCESS);
24: }
26: static PetscErrorCode PetscViewerFlush_Draw(PetscViewer v)
27: {
28: PetscInt i;
29: PetscViewer_Draw *vdraw = (PetscViewer_Draw *)v->data;
31: PetscFunctionBegin;
32: for (i = 0; i < vdraw->draw_max; i++) {
33: if (vdraw->draw[i]) PetscCall(PetscDrawFlush(vdraw->draw[i]));
34: }
35: PetscFunctionReturn(PETSC_SUCCESS);
36: }
38: /*@C
39: PetscViewerDrawGetDraw - Returns `PetscDraw` object from `PETSCVIEWERDRAW` `PetscViewer` object.
40: This `PetscDraw` object may then be used to perform graphics using `PetscDraw` commands.
42: Collective
44: Input Parameters:
45: + viewer - the `PetscViewer` (created with `PetscViewerDrawOpen()` of type `PETSCVIEWERDRAW`)
46: - windownumber - indicates which subwindow (usually 0) to obtain
48: Output Parameter:
49: . draw - the draw object
51: Level: intermediate
53: .seealso: [](sec_viewers), `PETSCVIEWERDRAW`, `PetscViewerDrawGetLG()`, `PetscViewerDrawGetAxis()`, `PetscViewerDrawOpen()`
54: @*/
55: PetscErrorCode PetscViewerDrawGetDraw(PetscViewer viewer, PetscInt windownumber, PetscDraw *draw)
56: {
57: PetscViewer_Draw *vdraw;
58: PetscBool isdraw;
60: PetscFunctionBegin;
64: PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERDRAW, &isdraw));
65: PetscCheck(isdraw, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Must be draw type PetscViewer");
66: PetscCheck(windownumber >= 0, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Window number cannot be negative");
67: vdraw = (PetscViewer_Draw *)viewer->data;
69: windownumber += vdraw->draw_base;
70: if (windownumber >= vdraw->draw_max) {
71: /* allocate twice as many slots as needed */
72: PetscInt draw_max = vdraw->draw_max;
73: PetscDraw *tdraw = vdraw->draw;
74: PetscDrawLG *drawlg = vdraw->drawlg;
75: PetscDrawAxis *drawaxis = vdraw->drawaxis;
77: vdraw->draw_max = 2 * windownumber;
79: PetscCall(PetscCalloc3(vdraw->draw_max, &vdraw->draw, vdraw->draw_max, &vdraw->drawlg, vdraw->draw_max, &vdraw->drawaxis));
80: PetscCall(PetscArraycpy(vdraw->draw, tdraw, draw_max));
81: PetscCall(PetscArraycpy(vdraw->drawlg, drawlg, draw_max));
82: PetscCall(PetscArraycpy(vdraw->drawaxis, drawaxis, draw_max));
83: PetscCall(PetscFree3(tdraw, drawlg, drawaxis));
84: }
86: if (!vdraw->draw[windownumber]) {
87: char *title = vdraw->title, tmp_str[128];
88: if (windownumber) {
89: PetscCall(PetscSNPrintf(tmp_str, sizeof(tmp_str), "%s:%" PetscInt_FMT, vdraw->title ? vdraw->title : "", windownumber));
90: title = tmp_str;
91: }
92: PetscCall(PetscDrawCreate(PetscObjectComm((PetscObject)viewer), vdraw->display, title, PETSC_DECIDE, PETSC_DECIDE, vdraw->w, vdraw->h, &vdraw->draw[windownumber]));
93: if (vdraw->drawtype) PetscCall(PetscDrawSetType(vdraw->draw[windownumber], vdraw->drawtype));
94: PetscCall(PetscDrawSetPause(vdraw->draw[windownumber], vdraw->pause));
95: PetscCall(PetscDrawSetOptionsPrefix(vdraw->draw[windownumber], ((PetscObject)viewer)->prefix));
96: PetscCall(PetscDrawSetFromOptions(vdraw->draw[windownumber]));
97: }
98: if (draw) *draw = vdraw->draw[windownumber];
100: PetscFunctionReturn(PETSC_SUCCESS);
101: }
103: /*@C
104: PetscViewerDrawBaseAdd - add to the base integer that is added to the `windownumber` passed to `PetscViewerDrawGetDraw()`
106: Logically Collective
108: Input Parameters:
109: + viewer - the `PetscViewer` (created with `PetscViewerDrawOpen()`)
110: - windownumber - how much to add to the base
112: Level: developer
114: Note:
115: A `PETSCVIEWERDRAW` may have multiple `PetscDraw` subwindows, this increases the number of the subwindow that is returned with `PetscViewerDrawGetDraw()`
117: .seealso: [](sec_viewers), `PetscViewerDrawGetLG()`, `PetscViewerDrawGetAxis()`, `PetscViewerDrawOpen()`, `PetscViewerDrawGetDraw()`, `PetscViewerDrawBaseSet()`
118: @*/
119: PetscErrorCode PetscViewerDrawBaseAdd(PetscViewer viewer, PetscInt windownumber)
120: {
121: PetscViewer_Draw *vdraw;
122: PetscBool isdraw;
124: PetscFunctionBegin;
127: PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERDRAW, &isdraw));
128: PetscCheck(isdraw, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Must be draw type PetscViewer");
129: vdraw = (PetscViewer_Draw *)viewer->data;
131: PetscCheck(windownumber + vdraw->draw_base >= 0, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Resulting base %" PetscInt_FMT " cannot be negative", windownumber + vdraw->draw_base);
132: vdraw->draw_base += windownumber;
133: PetscFunctionReturn(PETSC_SUCCESS);
134: }
136: /*@C
137: PetscViewerDrawBaseSet - sets the base integer that is added to the `windownumber` passed to `PetscViewerDrawGetDraw()`
139: Logically Collective
141: Input Parameters:
142: + viewer - the `PetscViewer` (created with `PetscViewerDrawOpen()`)
143: - windownumber - value to set the base
145: Level: developer
147: Note:
148: A `PETSCVIEWERDRAW` may have multiple `PetscDraw` subwindows, this increases the number of the subwindow that is returned with `PetscViewerDrawGetDraw()`
150: .seealso: [](sec_viewers), `PetscViewerDrawGetLG()`, `PetscViewerDrawGetAxis()`, `PetscViewerDrawOpen()`, `PetscViewerDrawGetDraw()`, `PetscViewerDrawBaseAdd()`
151: @*/
152: PetscErrorCode PetscViewerDrawBaseSet(PetscViewer viewer, PetscInt windownumber)
153: {
154: PetscViewer_Draw *vdraw;
155: PetscBool isdraw;
157: PetscFunctionBegin;
160: PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERDRAW, &isdraw));
161: PetscCheck(isdraw, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Must be draw type PetscViewer");
162: vdraw = (PetscViewer_Draw *)viewer->data;
164: PetscCheck(windownumber >= 0, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Resulting base %" PetscInt_FMT " cannot be negative", windownumber);
165: vdraw->draw_base = windownumber;
166: PetscFunctionReturn(PETSC_SUCCESS);
167: }
169: /*@C
170: PetscViewerDrawGetDrawLG - Returns a `PetscDrawLG` object from `PetscViewer` object of type `PETSCVIEWERDRAW`.
171: This `PetscDrawLG` object may then be used to perform graphics using `PetscDrawLG` commands.
173: Collective
175: Input Parameters:
176: + viewer - the `PetscViewer` (created with `PetscViewerDrawOpen()`)
177: - windownumber - indicates which subwindow (usually 0)
179: Output Parameter:
180: . draw - the draw line graph object
182: Level: intermediate
184: Note:
185: A `PETSCVIEWERDRAW` may have multiple `PetscDraw` subwindows
187: .seealso: [](sec_viewers), `PetscDrawLG`, `PetscViewerDrawGetDraw()`, `PetscViewerDrawGetAxis()`, `PetscViewerDrawOpen()`
188: @*/
189: PetscErrorCode PetscViewerDrawGetDrawLG(PetscViewer viewer, PetscInt windownumber, PetscDrawLG *drawlg)
190: {
191: PetscBool isdraw;
192: PetscViewer_Draw *vdraw;
194: PetscFunctionBegin;
198: PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERDRAW, &isdraw));
199: PetscCheck(isdraw, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Must be draw type PetscViewer");
200: PetscCheck(windownumber >= 0, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Window number cannot be negative");
201: vdraw = (PetscViewer_Draw *)viewer->data;
203: if (windownumber + vdraw->draw_base >= vdraw->draw_max || !vdraw->draw[windownumber + vdraw->draw_base]) PetscCall(PetscViewerDrawGetDraw(viewer, windownumber, NULL));
204: if (!vdraw->drawlg[windownumber + vdraw->draw_base]) {
205: PetscCall(PetscDrawLGCreate(vdraw->draw[windownumber + vdraw->draw_base], 1, &vdraw->drawlg[windownumber + vdraw->draw_base]));
206: PetscCall(PetscDrawLGSetFromOptions(vdraw->drawlg[windownumber + vdraw->draw_base]));
207: }
208: *drawlg = vdraw->drawlg[windownumber + vdraw->draw_base];
209: PetscFunctionReturn(PETSC_SUCCESS);
210: }
212: /*@C
213: PetscViewerDrawGetDrawAxis - Returns a `PetscDrawAxis` object from a `PetscViewer` object of type `PETSCVIEWERDRAW`.
214: This `PetscDrawAxis` object may then be used to perform graphics using `PetscDrawAxis` commands.
216: Collective
218: Input Parameters:
219: + viewer - the `PetscViewer` (created with `PetscViewerDrawOpen()`)
220: - windownumber - indicates which subwindow (usually 0)
222: Output Parameter:
223: . drawaxis - the draw axis object
225: Level: advanced
227: Note:
228: A `PETSCVIEWERDRAW` may have multiple `PetscDraw` subwindows
230: .seealso: [](sec_viewers), `PetscViewerDrawGetDraw()`, `PetscViewerDrawGetLG()`, `PetscViewerDrawOpen()`
231: @*/
232: PetscErrorCode PetscViewerDrawGetDrawAxis(PetscViewer viewer, PetscInt windownumber, PetscDrawAxis *drawaxis)
233: {
234: PetscBool isdraw;
235: PetscViewer_Draw *vdraw;
237: PetscFunctionBegin;
241: PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERDRAW, &isdraw));
242: PetscCheck(isdraw, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Must be draw type PetscViewer");
243: PetscCheck(windownumber >= 0, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Window number cannot be negative");
244: vdraw = (PetscViewer_Draw *)viewer->data;
246: if (windownumber + vdraw->draw_base >= vdraw->draw_max || !vdraw->draw[windownumber + vdraw->draw_base]) PetscCall(PetscViewerDrawGetDraw(viewer, windownumber, NULL));
247: if (!vdraw->drawaxis[windownumber + vdraw->draw_base]) PetscCall(PetscDrawAxisCreate(vdraw->draw[windownumber + vdraw->draw_base], &vdraw->drawaxis[windownumber + vdraw->draw_base]));
248: *drawaxis = vdraw->drawaxis[windownumber + vdraw->draw_base];
249: PetscFunctionReturn(PETSC_SUCCESS);
250: }
252: PetscErrorCode PetscViewerDrawResize(PetscViewer v, int w, int h)
253: {
254: PetscViewer_Draw *vdraw;
255: PetscBool isdraw;
257: PetscFunctionBegin;
259: PetscCall(PetscObjectTypeCompare((PetscObject)v, PETSCVIEWERDRAW, &isdraw));
260: if (!isdraw) PetscFunctionReturn(PETSC_SUCCESS);
261: vdraw = (PetscViewer_Draw *)v->data;
263: if (w >= 1) vdraw->w = w;
264: if (h >= 1) vdraw->h = h;
265: PetscFunctionReturn(PETSC_SUCCESS);
266: }
268: PetscErrorCode PetscViewerDrawSetInfo(PetscViewer v, const char display[], const char title[], int x, int y, int w, int h)
269: {
270: PetscViewer_Draw *vdraw;
271: PetscBool isdraw;
273: PetscFunctionBegin;
275: PetscCall(PetscObjectTypeCompare((PetscObject)v, PETSCVIEWERDRAW, &isdraw));
276: if (!isdraw) PetscFunctionReturn(PETSC_SUCCESS);
277: vdraw = (PetscViewer_Draw *)v->data;
279: PetscCall(PetscStrallocpy(display, &vdraw->display));
280: PetscCall(PetscStrallocpy(title, &vdraw->title));
281: if (w >= 1) vdraw->w = w;
282: if (h >= 1) vdraw->h = h;
283: PetscFunctionReturn(PETSC_SUCCESS);
284: }
286: PetscErrorCode PetscViewerDrawSetDrawType(PetscViewer v, PetscDrawType drawtype)
287: {
288: PetscViewer_Draw *vdraw;
289: PetscBool isdraw;
291: PetscFunctionBegin;
293: PetscCall(PetscObjectTypeCompare((PetscObject)v, PETSCVIEWERDRAW, &isdraw));
294: if (!isdraw) PetscFunctionReturn(PETSC_SUCCESS);
295: vdraw = (PetscViewer_Draw *)v->data;
297: PetscCall(PetscFree(vdraw->drawtype));
298: PetscCall(PetscStrallocpy(drawtype, (char **)&vdraw->drawtype));
299: PetscFunctionReturn(PETSC_SUCCESS);
300: }
302: PetscErrorCode PetscViewerDrawGetDrawType(PetscViewer v, PetscDrawType *drawtype)
303: {
304: PetscViewer_Draw *vdraw;
305: PetscBool isdraw;
307: PetscFunctionBegin;
309: PetscCall(PetscObjectTypeCompare((PetscObject)v, PETSCVIEWERDRAW, &isdraw));
310: PetscCheck(isdraw, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Must be draw type PetscViewer");
311: vdraw = (PetscViewer_Draw *)v->data;
313: *drawtype = vdraw->drawtype;
314: PetscFunctionReturn(PETSC_SUCCESS);
315: }
317: PetscErrorCode PetscViewerDrawSetTitle(PetscViewer v, const char title[])
318: {
319: PetscViewer_Draw *vdraw;
320: PetscBool isdraw;
322: PetscFunctionBegin;
324: PetscCall(PetscObjectTypeCompare((PetscObject)v, PETSCVIEWERDRAW, &isdraw));
325: if (!isdraw) PetscFunctionReturn(PETSC_SUCCESS);
326: vdraw = (PetscViewer_Draw *)v->data;
328: PetscCall(PetscFree(vdraw->title));
329: PetscCall(PetscStrallocpy(title, &vdraw->title));
330: PetscFunctionReturn(PETSC_SUCCESS);
331: }
333: PetscErrorCode PetscViewerDrawGetTitle(PetscViewer v, const char *title[])
334: {
335: PetscViewer_Draw *vdraw;
336: PetscBool isdraw;
338: PetscFunctionBegin;
340: PetscCall(PetscObjectTypeCompare((PetscObject)v, PETSCVIEWERDRAW, &isdraw));
341: PetscCheck(isdraw, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Must be draw type PetscViewer");
342: vdraw = (PetscViewer_Draw *)v->data;
344: *title = vdraw->title;
345: PetscFunctionReturn(PETSC_SUCCESS);
346: }
348: /*@C
349: PetscViewerDrawOpen - Opens a `PetscDraw` window for use as a `PetscViewer` with type `PETSCVIEWERDRAW`. If you want to
350: do graphics in this window, you must call `PetscViewerDrawGetDraw()` and
351: perform the graphics on the `PetscDraw` object.
353: Collective
355: Input Parameters:
356: + comm - communicator that will share window
357: . display - the X display on which to open, or `NULL` for the local machine
358: . title - the title to put in the title bar, or `NULL` for no title
359: . x - horizontal screen coordinate of the upper left corner of window, or use `PETSC_DECIDE`
360: . y - vertical screen coordinate of the upper left corner of window, or use `PETSC_DECIDE`
361: . 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`
362: - 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`
364: Output Parameter:
365: . viewer - the `PetscViewer`
367: Format Options:
368: + `PETSC_VIEWER_DRAW_BASIC` - displays with basic format
369: - `PETSC_VIEWER_DRAW_LG` - displays using a line graph
371: Options Database Keys:
372: + -draw_type - use x or null
373: . -nox - Disables all x-windows output
374: . -display <name> - Specifies name of machine for the X display
375: . -geometry <x,y,w,h> - allows setting the window location and size
376: - -draw_pause <pause> - Sets time (in seconds) that the
377: program pauses after PetscDrawPause() has been called
378: (0 is default, -1 implies until user input).
380: Level: beginner
382: Fortran Note:
383: Whenever indicating null character data in a Fortran code,
384: `PETSC_NULL_CHARACTER` must be employed; using NULL is not
385: correct for character data! Thus, `PETSC_NULL_CHARACTER` can be
386: used for the display and title input parameters.
388: .seealso: [](sec_viewers), `PETSCVIEWERDRAW`, `PetscDrawCreate()`, `PetscViewerDestroy()`, `PetscViewerDrawGetDraw()`, `PetscViewerCreate()`, `PETSC_VIEWER_DRAW_`,
389: `PETSC_VIEWER_DRAW_WORLD`, `PETSC_VIEWER_DRAW_SELF`
390: @*/
391: PetscErrorCode PetscViewerDrawOpen(MPI_Comm comm, const char display[], const char title[], int x, int y, int w, int h, PetscViewer *viewer)
392: {
393: PetscFunctionBegin;
394: PetscCall(PetscViewerCreate(comm, viewer));
395: PetscCall(PetscViewerSetType(*viewer, PETSCVIEWERDRAW));
396: PetscCall(PetscViewerDrawSetInfo(*viewer, display, title, x, y, w, h));
397: PetscFunctionReturn(PETSC_SUCCESS);
398: }
400: #include <petsc/private/drawimpl.h>
402: PetscErrorCode PetscViewerGetSubViewer_Draw(PetscViewer viewer, MPI_Comm comm, PetscViewer *sviewer)
403: {
404: PetscMPIInt rank;
405: PetscInt i;
406: PetscViewer_Draw *vdraw = (PetscViewer_Draw *)viewer->data, *svdraw;
408: PetscFunctionBegin;
409: PetscCheck(!vdraw->singleton_made, PETSC_COMM_SELF, PETSC_ERR_ORDER, "Trying to get SubViewer without first restoring previous");
410: /* only processor zero can use the PetscViewer draw singleton */
411: if (sviewer) *sviewer = NULL;
412: PetscCallMPI(MPI_Comm_rank(PetscObjectComm((PetscObject)viewer), &rank));
413: if (rank == 0) {
414: PetscMPIInt flg;
415: PetscDraw draw, sdraw;
417: PetscCallMPI(MPI_Comm_compare(PETSC_COMM_SELF, comm, &flg));
418: PetscCheck(flg == MPI_IDENT || flg == MPI_CONGRUENT, PETSC_COMM_SELF, PETSC_ERR_SUP, "PetscViewerGetSubViewer() for PETSCVIEWERDRAW requires a singleton MPI_Comm");
419: PetscCall(PetscViewerCreate(comm, sviewer));
420: PetscCall(PetscViewerSetType(*sviewer, PETSCVIEWERDRAW));
421: svdraw = (PetscViewer_Draw *)(*sviewer)->data;
422: (*sviewer)->format = viewer->format;
423: for (i = 0; i < vdraw->draw_max; i++) { /* XXX this is wrong if svdraw->draw_max (initially 5) < vdraw->draw_max */
424: if (vdraw->draw[i]) PetscCall(PetscDrawGetSingleton(vdraw->draw[i], &svdraw->draw[i]));
425: }
426: PetscCall(PetscViewerDrawGetDraw(viewer, 0, &draw));
427: PetscCall(PetscViewerDrawGetDraw(*sviewer, 0, &sdraw));
428: if (draw->savefilename) {
429: PetscCall(PetscDrawSetSave(sdraw, draw->savefilename));
430: sdraw->savefilecount = draw->savefilecount;
431: sdraw->savesinglefile = draw->savesinglefile;
432: sdraw->savemoviefps = draw->savemoviefps;
433: sdraw->saveonclear = draw->saveonclear;
434: sdraw->saveonflush = draw->saveonflush;
435: }
436: if (draw->savefinalfilename) PetscCall(PetscDrawSetSaveFinalImage(sdraw, draw->savefinalfilename));
437: } else {
438: PetscDraw draw;
439: PetscCall(PetscViewerDrawGetDraw(viewer, 0, &draw));
440: }
441: vdraw->singleton_made = PETSC_TRUE;
442: PetscFunctionReturn(PETSC_SUCCESS);
443: }
445: PetscErrorCode PetscViewerRestoreSubViewer_Draw(PetscViewer viewer, MPI_Comm comm, PetscViewer *sviewer)
446: {
447: PetscMPIInt rank;
448: PetscInt i;
449: PetscViewer_Draw *vdraw = (PetscViewer_Draw *)viewer->data, *svdraw;
451: PetscFunctionBegin;
452: PetscCheck(vdraw->singleton_made, PETSC_COMM_SELF, PETSC_ERR_ORDER, "Trying to restore a singleton that was not gotten");
453: PetscCallMPI(MPI_Comm_rank(PetscObjectComm((PetscObject)viewer), &rank));
454: if (rank == 0) {
455: PetscDraw draw, sdraw;
457: PetscCall(PetscViewerDrawGetDraw(viewer, 0, &draw));
458: PetscCall(PetscViewerDrawGetDraw(*sviewer, 0, &sdraw));
459: if (draw->savefilename) {
460: draw->savefilecount = sdraw->savefilecount;
461: PetscCallMPI(MPI_Bcast(&draw->savefilecount, 1, MPIU_INT, 0, PetscObjectComm((PetscObject)draw)));
462: }
463: svdraw = (PetscViewer_Draw *)(*sviewer)->data;
464: for (i = 0; i < vdraw->draw_max; i++) {
465: if (vdraw->draw[i] && svdraw->draw[i]) PetscCall(PetscDrawRestoreSingleton(vdraw->draw[i], &svdraw->draw[i]));
466: }
467: PetscCall(PetscFree3(svdraw->draw, svdraw->drawlg, svdraw->drawaxis));
468: PetscCall(PetscFree((*sviewer)->data));
469: PetscCall(PetscHeaderDestroy(sviewer));
470: } else {
471: PetscDraw draw;
473: PetscCall(PetscViewerDrawGetDraw(viewer, 0, &draw));
474: if (draw->savefilename) PetscCallMPI(MPI_Bcast(&draw->savefilecount, 1, MPIU_INT, 0, PetscObjectComm((PetscObject)draw)));
475: }
477: vdraw->singleton_made = PETSC_FALSE;
478: PetscFunctionReturn(PETSC_SUCCESS);
479: }
481: PetscErrorCode PetscViewerSetFromOptions_Draw(PetscViewer v, PetscOptionItems *PetscOptionsObject)
482: {
483: PetscReal bounds[16];
484: PetscInt nbounds = 16;
485: PetscBool flg;
487: PetscFunctionBegin;
488: PetscOptionsHeadBegin(PetscOptionsObject, "Draw PetscViewer Options");
489: PetscCall(PetscOptionsRealArray("-draw_bounds", "Bounds to put on plots axis", "PetscViewerDrawSetBounds", bounds, &nbounds, &flg));
490: if (flg) PetscCall(PetscViewerDrawSetBounds(v, nbounds / 2, bounds));
491: PetscOptionsHeadEnd();
492: PetscFunctionReturn(PETSC_SUCCESS);
493: }
495: PetscErrorCode PetscViewerView_Draw(PetscViewer viewer, PetscViewer v)
496: {
497: PetscDraw draw;
498: PetscInt i;
499: PetscViewer_Draw *vdraw = (PetscViewer_Draw *)viewer->data;
500: PetscBool iascii;
502: PetscFunctionBegin;
503: PetscCall(PetscObjectTypeCompare((PetscObject)v, PETSCVIEWERASCII, &iascii));
504: if (iascii) PetscCall(PetscViewerASCIIPrintf(v, "Draw viewer is of type %s\n", vdraw->drawtype));
505: /* If the PetscViewer has just been created then no vdraw->draw yet
506: exists so this will not actually call the viewer on any draws. */
507: for (i = 0; i < vdraw->draw_base; i++) {
508: if (vdraw->draw[i]) {
509: PetscCall(PetscViewerDrawGetDraw(viewer, i, &draw));
510: PetscCall(PetscDrawView(draw, v));
511: }
512: }
513: PetscFunctionReturn(PETSC_SUCCESS);
514: }
516: /*MC
517: PETSCVIEWERDRAW - A viewer that generates graphics, either to the screen or a file
519: Level: beginner
521: .seealso: [](sec_viewers), `PetscViewerDrawOpen()`, `PetscViewerDrawGetDraw()`, `PETSC_VIEWER_DRAW_()`, `PETSC_VIEWER_DRAW_SELF`, `PETSC_VIEWER_DRAW_WORLD`,
522: `PetscViewerCreate()`, `PetscViewerASCIIOpen()`, `PetscViewerBinaryOpen()`, `PETSCVIEWERBINARY`,
523: `PetscViewerMatlabOpen()`, `VecView()`, `DMView()`, `PetscViewerMatlabPutArray()`, `PETSCVIEWERASCII`, `PETSCVIEWERMATLAB`,
524: `PetscViewerFileSetName()`, `PetscViewerFileSetMode()`, `PetscViewerFormat`, `PetscViewerType`, `PetscViewerSetType()`
525: M*/
526: PETSC_EXTERN PetscErrorCode PetscViewerCreate_Draw(PetscViewer viewer)
527: {
528: PetscViewer_Draw *vdraw;
530: PetscFunctionBegin;
531: PetscCall(PetscNew(&vdraw));
532: viewer->data = (void *)vdraw;
534: viewer->ops->flush = PetscViewerFlush_Draw;
535: viewer->ops->view = PetscViewerView_Draw;
536: viewer->ops->destroy = PetscViewerDestroy_Draw;
537: viewer->ops->setfromoptions = PetscViewerSetFromOptions_Draw;
538: viewer->ops->getsubviewer = PetscViewerGetSubViewer_Draw;
539: viewer->ops->restoresubviewer = PetscViewerRestoreSubViewer_Draw;
541: /* these are created on the fly if requested */
542: vdraw->draw_max = 5;
543: vdraw->draw_base = 0;
544: vdraw->w = PETSC_DECIDE;
545: vdraw->h = PETSC_DECIDE;
547: PetscCall(PetscCalloc3(vdraw->draw_max, &vdraw->draw, vdraw->draw_max, &vdraw->drawlg, vdraw->draw_max, &vdraw->drawaxis));
548: vdraw->singleton_made = PETSC_FALSE;
549: PetscFunctionReturn(PETSC_SUCCESS);
550: }
552: /*@
553: PetscViewerDrawClear - Clears a `PetscDraw` graphic associated with a `PetscViewer`.
555: Not Collective
557: Input Parameter:
558: . viewer - the `PetscViewer`
560: Level: intermediate
562: .seealso: [](sec_viewers), `PETSCVIEWERDRAW`, `PetscViewerDrawOpen()`, `PetscViewerDrawGetDraw()`,
563: @*/
564: PetscErrorCode PetscViewerDrawClear(PetscViewer viewer)
565: {
566: PetscViewer_Draw *vdraw;
567: PetscBool isdraw;
568: PetscInt i;
570: PetscFunctionBegin;
572: PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERDRAW, &isdraw));
573: if (!isdraw) PetscFunctionReturn(PETSC_SUCCESS);
574: vdraw = (PetscViewer_Draw *)viewer->data;
576: for (i = 0; i < vdraw->draw_max; i++) {
577: if (vdraw->draw[i]) PetscCall(PetscDrawClear(vdraw->draw[i]));
578: }
579: PetscFunctionReturn(PETSC_SUCCESS);
580: }
582: /*@
583: PetscViewerDrawGetPause - Gets the pause value (how long to pause before an image is changed) in the `PETSCVIEWERDRAW` `PetscViewer`
585: Not Collective
587: Input Parameter:
588: . viewer - the `PetscViewer`
590: Output Parameter:
591: . pause - the pause value
593: Level: intermediate
595: .seealso: [](sec_viewers), `PETSCVIEWERDRAW`, `PetscViewerDrawOpen()`, `PetscViewerDrawGetDraw()`,
596: @*/
597: PetscErrorCode PetscViewerDrawGetPause(PetscViewer viewer, PetscReal *pause)
598: {
599: PetscViewer_Draw *vdraw;
600: PetscBool isdraw;
601: PetscInt i;
602: PetscDraw draw;
604: PetscFunctionBegin;
606: PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERDRAW, &isdraw));
607: if (!isdraw) {
608: *pause = 0.0;
609: PetscFunctionReturn(PETSC_SUCCESS);
610: }
611: vdraw = (PetscViewer_Draw *)viewer->data;
613: for (i = 0; i < vdraw->draw_max; i++) {
614: if (vdraw->draw[i]) {
615: PetscCall(PetscDrawGetPause(vdraw->draw[i], pause));
616: PetscFunctionReturn(PETSC_SUCCESS);
617: }
618: }
619: /* none exist yet so create one and get its pause */
620: PetscCall(PetscViewerDrawGetDraw(viewer, 0, &draw));
621: PetscCall(PetscDrawGetPause(draw, pause));
622: PetscFunctionReturn(PETSC_SUCCESS);
623: }
625: /*@
626: PetscViewerDrawSetPause - Sets a pause for each `PetscDraw` in the `PETSCVIEWERDRAW` `PetscViewer`
628: Not Collective
630: Input Parameters:
631: + viewer - the `PetscViewer`
632: - pause - the pause value
634: Level: intermediate
636: .seealso: [](sec_viewers), `PETSCVIEWERDRAW`, `PetscViewerDrawOpen()`, `PetscViewerDrawGetDraw()`,
637: @*/
638: PetscErrorCode PetscViewerDrawSetPause(PetscViewer viewer, PetscReal pause)
639: {
640: PetscViewer_Draw *vdraw;
641: PetscBool isdraw;
642: PetscInt i;
644: PetscFunctionBegin;
646: PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERDRAW, &isdraw));
647: if (!isdraw) PetscFunctionReturn(PETSC_SUCCESS);
648: vdraw = (PetscViewer_Draw *)viewer->data;
650: vdraw->pause = pause;
651: for (i = 0; i < vdraw->draw_max; i++) {
652: if (vdraw->draw[i]) PetscCall(PetscDrawSetPause(vdraw->draw[i], pause));
653: }
654: PetscFunctionReturn(PETSC_SUCCESS);
655: }
657: /*@
658: PetscViewerDrawSetHold - Holds previous image when drawing new image in a `PETSCVIEWERDRAW`
660: Not Collective
662: Input Parameters:
663: + viewer - the `PetscViewer`
664: - hold - `PETSC_TRUE` indicates to hold the previous image
666: Level: intermediate
668: .seealso: [](sec_viewers), `PETSCVIEWERDRAW`, `PetscViewerDrawOpen()`, `PetscViewerDrawGetDraw()`,
669: @*/
670: PetscErrorCode PetscViewerDrawSetHold(PetscViewer viewer, PetscBool hold)
671: {
672: PetscViewer_Draw *vdraw;
673: PetscBool isdraw;
675: PetscFunctionBegin;
677: PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERDRAW, &isdraw));
678: if (!isdraw) PetscFunctionReturn(PETSC_SUCCESS);
679: vdraw = (PetscViewer_Draw *)viewer->data;
681: vdraw->hold = hold;
682: PetscFunctionReturn(PETSC_SUCCESS);
683: }
685: /*@
686: PetscViewerDrawGetHold - Checks if the `PETSCVIEWERDRAW` `PetscViewer` holds previous image when drawing new image
688: Not Collective
690: Input Parameter:
691: . viewer - the `PetscViewer`
693: Output Parameter:
694: . hold - indicates to hold or not
696: Level: intermediate
698: .seealso: [](sec_viewers), `PETSCVIEWERDRAW`, `PetscViewerDrawOpen()`, `PetscViewerDrawGetDraw()`,
699: @*/
700: PetscErrorCode PetscViewerDrawGetHold(PetscViewer viewer, PetscBool *hold)
701: {
702: PetscViewer_Draw *vdraw;
703: PetscBool isdraw;
705: PetscFunctionBegin;
707: PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERDRAW, &isdraw));
708: if (!isdraw) {
709: *hold = PETSC_FALSE;
710: PetscFunctionReturn(PETSC_SUCCESS);
711: }
712: vdraw = (PetscViewer_Draw *)viewer->data;
714: *hold = vdraw->hold;
715: PetscFunctionReturn(PETSC_SUCCESS);
716: }
718: /*
719: The variable Petsc_Viewer_Draw_keyval is used to indicate an MPI attribute that
720: is attached to a communicator, in this case the attribute is a PetscViewer.
721: */
722: PetscMPIInt Petsc_Viewer_Draw_keyval = MPI_KEYVAL_INVALID;
724: /*@C
725: PETSC_VIEWER_DRAW_ - Creates a window `PETSCVIEWERDRAW` `PetscViewer` shared by all processors
726: in an MPI communicator.
728: Collective
730: Input Parameter:
731: . comm - the MPI communicator to share the window `PetscViewer`
733: Level: intermediate
735: Note:
736: Unlike almost all other PETSc routines, `PETSC_VIEWER_DRAW_()` does not return
737: an error code. The window is usually used in the form
738: $ XXXView(XXX object, PETSC_VIEWER_DRAW_(comm));
740: .seealso: [](sec_viewers), `PETSCVIEWERDRAW`, `PetscViewer`, `PETSC_VIEWER_DRAW_WORLD`, `PETSC_VIEWER_DRAW_SELF`, `PetscViewerDrawOpen()`,
741: @*/
742: PetscViewer PETSC_VIEWER_DRAW_(MPI_Comm comm)
743: {
744: PetscErrorCode ierr;
745: PetscMPIInt flag, mpi_ierr;
746: PetscViewer viewer;
747: MPI_Comm ncomm;
749: PetscFunctionBegin;
750: ierr = PetscCommDuplicate(comm, &ncomm, NULL);
751: if (ierr) {
752: ierr = PetscError(PETSC_COMM_SELF, __LINE__, "PETSC_VIEWER_DRAW_", __FILE__, PETSC_ERR_PLIB, PETSC_ERROR_INITIAL, " ");
753: PetscFunctionReturn(NULL);
754: }
755: if (Petsc_Viewer_Draw_keyval == MPI_KEYVAL_INVALID) {
756: mpi_ierr = MPI_Comm_create_keyval(MPI_COMM_NULL_COPY_FN, MPI_COMM_NULL_DELETE_FN, &Petsc_Viewer_Draw_keyval, NULL);
757: if (mpi_ierr) {
758: ierr = PetscError(PETSC_COMM_SELF, __LINE__, "PETSC_VIEWER_DRAW_", __FILE__, PETSC_ERR_PLIB, PETSC_ERROR_INITIAL, " ");
759: PetscFunctionReturn(NULL);
760: }
761: }
762: mpi_ierr = MPI_Comm_get_attr(ncomm, Petsc_Viewer_Draw_keyval, (void **)&viewer, &flag);
763: if (mpi_ierr) {
764: ierr = PetscError(PETSC_COMM_SELF, __LINE__, "PETSC_VIEWER_DRAW_", __FILE__, PETSC_ERR_PLIB, PETSC_ERROR_INITIAL, " ");
765: PetscFunctionReturn(NULL);
766: }
767: if (!flag) { /* PetscViewer not yet created */
768: ierr = PetscViewerDrawOpen(ncomm, NULL, NULL, PETSC_DECIDE, PETSC_DECIDE, 300, 300, &viewer);
769: if (ierr) {
770: ierr = PetscError(PETSC_COMM_SELF, __LINE__, "PETSC_VIEWER_DRAW_", __FILE__, PETSC_ERR_PLIB, PETSC_ERROR_REPEAT, " ");
771: PetscFunctionReturn(NULL);
772: }
773: ierr = PetscObjectRegisterDestroy((PetscObject)viewer);
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: mpi_ierr = MPI_Comm_set_attr(ncomm, Petsc_Viewer_Draw_keyval, (void *)viewer);
779: if (mpi_ierr) {
780: ierr = PetscError(PETSC_COMM_SELF, __LINE__, "PETSC_VIEWER_DRAW_", __FILE__, PETSC_ERR_PLIB, PETSC_ERROR_INITIAL, " ");
781: PetscFunctionReturn(NULL);
782: }
783: }
784: ierr = PetscCommDestroy(&ncomm);
785: if (ierr) {
786: ierr = PetscError(PETSC_COMM_SELF, __LINE__, "PETSC_VIEWER_DRAW_", __FILE__, PETSC_ERR_PLIB, PETSC_ERROR_REPEAT, " ");
787: PetscFunctionReturn(NULL);
788: }
789: PetscFunctionReturn(viewer);
790: }
792: /*@
793: PetscViewerDrawSetBounds - sets the upper and lower bounds to be used in plotting in a `PETSCVIEWERDRAW` `PetscViewer`
795: Collective
797: Input Parameters:
798: + viewer - the Petsc`Viewer` (created with `PetscViewerDrawOpen()`)
799: . nbounds - number of plots that can be made with this viewer, for example the dof passed to `DMDACreate()`
800: - 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, .....
802: Options Database Key:
803: . -draw_bounds minF0,maxF0,minF1,maxF1 - the lower left and upper right bounds
805: Level: intermediate
807: Note:
808: 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
809: 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
810: this viewer. Otherwise the color to physical value meaning changes with each new image if this is not set.
812: .seealso: [](sec_viewers), `PETSCVIEWERDRAW`, `PetscViewerDrawGetLG()`, `PetscViewerDrawGetAxis()`, `PetscViewerDrawOpen()`
813: @*/
814: PetscErrorCode PetscViewerDrawSetBounds(PetscViewer viewer, PetscInt nbounds, const PetscReal *bounds)
815: {
816: PetscViewer_Draw *vdraw;
817: PetscBool isdraw;
819: PetscFunctionBegin;
821: PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERDRAW, &isdraw));
822: if (!isdraw) PetscFunctionReturn(PETSC_SUCCESS);
823: vdraw = (PetscViewer_Draw *)viewer->data;
825: vdraw->nbounds = nbounds;
826: PetscCall(PetscFree(vdraw->bounds));
827: PetscCall(PetscMalloc1(2 * nbounds, &vdraw->bounds));
828: PetscCall(PetscArraycpy(vdraw->bounds, bounds, 2 * nbounds));
829: PetscFunctionReturn(PETSC_SUCCESS);
830: }
832: /*@C
833: PetscViewerDrawGetBounds - gets the upper and lower bounds to be used in plotting set with `PetscViewerDrawSetBounds()`
835: Collective
837: Input Parameter:
838: . viewer - the `PetscViewer` (created with `PetscViewerDrawOpen()`)
840: Output Parameters:
841: + nbounds - number of plots that can be made with this viewer, for example the dof passed to `DMDACreate()`
842: - 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, .....
844: Level: intermediate
846: .seealso: [](sec_viewers), `PETSCVIEWERDRAW`, `PetscViewerDrawGetLG()`, `PetscViewerDrawGetAxis()`, `PetscViewerDrawOpen()`, `PetscViewerDrawSetBounds()`
847: @*/
848: PetscErrorCode PetscViewerDrawGetBounds(PetscViewer viewer, PetscInt *nbounds, const PetscReal **bounds)
849: {
850: PetscViewer_Draw *vdraw;
851: PetscBool isdraw;
853: PetscFunctionBegin;
855: PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERDRAW, &isdraw));
856: if (!isdraw) {
857: if (nbounds) *nbounds = 0;
858: if (bounds) *bounds = NULL;
859: PetscFunctionReturn(PETSC_SUCCESS);
860: }
861: vdraw = (PetscViewer_Draw *)viewer->data;
863: if (nbounds) *nbounds = vdraw->nbounds;
864: if (bounds) *bounds = vdraw->bounds;
865: PetscFunctionReturn(PETSC_SUCCESS);
866: }