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 `PetscViewer` object.
40: This `PetscDraw` object may then be used to perform graphics using
41: `PetscDraw` commands.
43: Collective
45: Input Parameters:
46: + viewer - the `PetscViewer` (created with `PetscViewerDrawOpen()` of type `PETSCVIEWERDRAW`)
47: - windownumber - indicates which subwindow (usually 0)
49: Output Parameter:
50: . draw - the draw object
52: Level: intermediate
54: .seealso: [](sec_viewers), `PETSCVIEWERDRAW`, `PetscViewerDrawGetLG()`, `PetscViewerDrawGetAxis()`, `PetscViewerDrawOpen()`
55: @*/
56: PetscErrorCode PetscViewerDrawGetDraw(PetscViewer viewer, PetscInt windownumber, PetscDraw *draw)
57: {
58: PetscViewer_Draw *vdraw;
59: PetscBool isdraw;
61: PetscFunctionBegin;
65: PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERDRAW, &isdraw));
66: PetscCheck(isdraw, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Must be draw type PetscViewer");
67: PetscCheck(windownumber >= 0, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Window number cannot be negative");
68: vdraw = (PetscViewer_Draw *)viewer->data;
70: windownumber += vdraw->draw_base;
71: if (windownumber >= vdraw->draw_max) {
72: /* allocate twice as many slots as needed */
73: PetscInt draw_max = vdraw->draw_max;
74: PetscDraw *tdraw = vdraw->draw;
75: PetscDrawLG *drawlg = vdraw->drawlg;
76: PetscDrawAxis *drawaxis = vdraw->drawaxis;
78: vdraw->draw_max = 2 * windownumber;
80: PetscCall(PetscCalloc3(vdraw->draw_max, &vdraw->draw, vdraw->draw_max, &vdraw->drawlg, vdraw->draw_max, &vdraw->drawaxis));
81: PetscCall(PetscArraycpy(vdraw->draw, tdraw, draw_max));
82: PetscCall(PetscArraycpy(vdraw->drawlg, drawlg, draw_max));
83: PetscCall(PetscArraycpy(vdraw->drawaxis, drawaxis, draw_max));
84: PetscCall(PetscFree3(tdraw, drawlg, drawaxis));
85: }
87: if (!vdraw->draw[windownumber]) {
88: char *title = vdraw->title, tmp_str[128];
89: if (windownumber) {
90: PetscCall(PetscSNPrintf(tmp_str, sizeof(tmp_str), "%s:%" PetscInt_FMT, vdraw->title ? vdraw->title : "", windownumber));
91: title = tmp_str;
92: }
93: PetscCall(PetscDrawCreate(PetscObjectComm((PetscObject)viewer), vdraw->display, title, PETSC_DECIDE, PETSC_DECIDE, vdraw->w, vdraw->h, &vdraw->draw[windownumber]));
94: if (vdraw->drawtype) PetscCall(PetscDrawSetType(vdraw->draw[windownumber], vdraw->drawtype));
95: PetscCall(PetscDrawSetPause(vdraw->draw[windownumber], vdraw->pause));
96: PetscCall(PetscDrawSetOptionsPrefix(vdraw->draw[windownumber], ((PetscObject)viewer)->prefix));
97: PetscCall(PetscDrawSetFromOptions(vdraw->draw[windownumber]));
98: }
99: if (draw) *draw = vdraw->draw[windownumber];
101: PetscFunctionReturn(PETSC_SUCCESS);
102: }
104: /*@C
105: PetscViewerDrawBaseAdd - add to the base integer that is added to the windownumber passed to `PetscViewerDrawGetDraw()`
107: Logically Collective
109: Input Parameters:
110: + viewer - the `PetscViewer` (created with `PetscViewerDrawOpen()`)
111: - windownumber - how much to add to the base
113: Level: developer
115: Note:
116: A `PETSCVIEWERDRAW` may have multiple `PetscDraw` subwindows, this increases the number of the subwindow that is returned with `PetscViewerDrawGetDraw()`
118: .seealso: [](sec_viewers), `PetscViewerDrawGetLG()`, `PetscViewerDrawGetAxis()`, `PetscViewerDrawOpen()`, `PetscViewerDrawGetDraw()`, `PetscViewerDrawBaseSet()`
119: @*/
120: PetscErrorCode PetscViewerDrawBaseAdd(PetscViewer viewer, PetscInt windownumber)
121: {
122: PetscViewer_Draw *vdraw;
123: PetscBool isdraw;
125: PetscFunctionBegin;
128: PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERDRAW, &isdraw));
129: PetscCheck(isdraw, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Must be draw type PetscViewer");
130: vdraw = (PetscViewer_Draw *)viewer->data;
132: PetscCheck(windownumber + vdraw->draw_base >= 0, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Resulting base %" PetscInt_FMT " cannot be negative", windownumber + vdraw->draw_base);
133: vdraw->draw_base += windownumber;
134: PetscFunctionReturn(PETSC_SUCCESS);
135: }
137: /*@C
138: PetscViewerDrawBaseSet - sets the base integer that is added to the windownumber passed to `PetscViewerDrawGetDraw()`
140: Logically Collective
142: Input Parameters:
143: + viewer - the `PetscViewer` (created with `PetscViewerDrawOpen()`)
144: - windownumber - value to set the base
146: Level: developer
148: Note:
149: A `PETSCVIEWERDRAW` may have multiple `PetscDraw` subwindows, this increases the number of the subwindow that is returned with `PetscViewerDrawGetDraw()`
151: .seealso: [](sec_viewers), `PetscViewerDrawGetLG()`, `PetscViewerDrawGetAxis()`, `PetscViewerDrawOpen()`, `PetscViewerDrawGetDraw()`, `PetscViewerDrawBaseAdd()`
152: @*/
153: PetscErrorCode PetscViewerDrawBaseSet(PetscViewer viewer, PetscInt windownumber)
154: {
155: PetscViewer_Draw *vdraw;
156: PetscBool isdraw;
158: PetscFunctionBegin;
161: PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERDRAW, &isdraw));
162: PetscCheck(isdraw, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Must be draw type PetscViewer");
163: vdraw = (PetscViewer_Draw *)viewer->data;
165: PetscCheck(windownumber >= 0, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Resulting base %" PetscInt_FMT " cannot be negative", windownumber);
166: vdraw->draw_base = windownumber;
167: PetscFunctionReturn(PETSC_SUCCESS);
168: }
170: /*@C
171: PetscViewerDrawGetDrawLG - Returns a `PetscDrawLG` object from `PetscViewer` object of type `PETSCVIEWERDRAW`.
172: This `PetscDrawLG` object may then be used to perform graphics using `PetscDrawLG` commands.
174: Collective
176: Input Parameters:
177: + viewer - the `PetscViewer` (created with `PetscViewerDrawOpen()`)
178: - windownumber - indicates which subwindow (usually 0)
180: Output Parameter:
181: . draw - the draw line graph object
183: Level: intermediate
185: Note:
186: A `PETSCVIEWERDRAW` may have multiple `PetscDraw` subwindows
188: .seealso: [](sec_viewers), `PetscDrawLG`, `PetscViewerDrawGetDraw()`, `PetscViewerDrawGetAxis()`, `PetscViewerDrawOpen()`
189: @*/
190: PetscErrorCode PetscViewerDrawGetDrawLG(PetscViewer viewer, PetscInt windownumber, PetscDrawLG *drawlg)
191: {
192: PetscBool isdraw;
193: PetscViewer_Draw *vdraw;
195: PetscFunctionBegin;
199: PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERDRAW, &isdraw));
200: PetscCheck(isdraw, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Must be draw type PetscViewer");
201: PetscCheck(windownumber >= 0, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Window number cannot be negative");
202: vdraw = (PetscViewer_Draw *)viewer->data;
204: if (windownumber + vdraw->draw_base >= vdraw->draw_max || !vdraw->draw[windownumber + vdraw->draw_base]) PetscCall(PetscViewerDrawGetDraw(viewer, windownumber, NULL));
205: if (!vdraw->drawlg[windownumber + vdraw->draw_base]) {
206: PetscCall(PetscDrawLGCreate(vdraw->draw[windownumber + vdraw->draw_base], 1, &vdraw->drawlg[windownumber + vdraw->draw_base]));
207: PetscCall(PetscDrawLGSetFromOptions(vdraw->drawlg[windownumber + vdraw->draw_base]));
208: }
209: *drawlg = vdraw->drawlg[windownumber + vdraw->draw_base];
210: PetscFunctionReturn(PETSC_SUCCESS);
211: }
213: /*@C
214: PetscViewerDrawGetDrawAxis - Returns a `PetscDrawAxis` object from a `PetscViewer` object of type `PETSCVIEWERDRAW`.
215: This `PetscDrawAxis` object may then be used to perform graphics using `PetscDrawAxis` commands.
217: Collective
219: Input Parameters:
220: + viewer - the `PetscViewer` (created with `PetscViewerDrawOpen()`)
221: - windownumber - indicates which subwindow (usually 0)
223: Output Parameter:
224: . drawaxis - the draw axis object
226: Level: advanced
228: Note:
229: A `PETSCVIEWERDRAW` may have multiple `PetscDraw` subwindows
231: .seealso: [](sec_viewers), `PetscViewerDrawGetDraw()`, `PetscViewerDrawGetLG()`, `PetscViewerDrawOpen()`
232: @*/
233: PetscErrorCode PetscViewerDrawGetDrawAxis(PetscViewer viewer, PetscInt windownumber, PetscDrawAxis *drawaxis)
234: {
235: PetscBool isdraw;
236: PetscViewer_Draw *vdraw;
238: PetscFunctionBegin;
242: PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERDRAW, &isdraw));
243: PetscCheck(isdraw, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Must be draw type PetscViewer");
244: PetscCheck(windownumber >= 0, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Window number cannot be negative");
245: vdraw = (PetscViewer_Draw *)viewer->data;
247: if (windownumber + vdraw->draw_base >= vdraw->draw_max || !vdraw->draw[windownumber + vdraw->draw_base]) PetscCall(PetscViewerDrawGetDraw(viewer, windownumber, NULL));
248: if (!vdraw->drawaxis[windownumber + vdraw->draw_base]) PetscCall(PetscDrawAxisCreate(vdraw->draw[windownumber + vdraw->draw_base], &vdraw->drawaxis[windownumber + vdraw->draw_base]));
249: *drawaxis = vdraw->drawaxis[windownumber + vdraw->draw_base];
250: PetscFunctionReturn(PETSC_SUCCESS);
251: }
253: PetscErrorCode PetscViewerDrawResize(PetscViewer v, int w, int h)
254: {
255: PetscViewer_Draw *vdraw;
256: PetscBool isdraw;
258: PetscFunctionBegin;
260: PetscCall(PetscObjectTypeCompare((PetscObject)v, PETSCVIEWERDRAW, &isdraw));
261: if (!isdraw) PetscFunctionReturn(PETSC_SUCCESS);
262: vdraw = (PetscViewer_Draw *)v->data;
264: if (w >= 1) vdraw->w = w;
265: if (h >= 1) vdraw->h = h;
266: PetscFunctionReturn(PETSC_SUCCESS);
267: }
269: PetscErrorCode PetscViewerDrawSetInfo(PetscViewer v, const char display[], const char title[], int x, int y, int w, int h)
270: {
271: PetscViewer_Draw *vdraw;
272: PetscBool isdraw;
274: PetscFunctionBegin;
276: PetscCall(PetscObjectTypeCompare((PetscObject)v, PETSCVIEWERDRAW, &isdraw));
277: if (!isdraw) PetscFunctionReturn(PETSC_SUCCESS);
278: vdraw = (PetscViewer_Draw *)v->data;
280: PetscCall(PetscStrallocpy(display, &vdraw->display));
281: PetscCall(PetscStrallocpy(title, &vdraw->title));
282: if (w >= 1) vdraw->w = w;
283: if (h >= 1) vdraw->h = h;
284: PetscFunctionReturn(PETSC_SUCCESS);
285: }
287: PetscErrorCode PetscViewerDrawSetDrawType(PetscViewer v, PetscDrawType drawtype)
288: {
289: PetscViewer_Draw *vdraw;
290: PetscBool isdraw;
292: PetscFunctionBegin;
294: PetscCall(PetscObjectTypeCompare((PetscObject)v, PETSCVIEWERDRAW, &isdraw));
295: if (!isdraw) PetscFunctionReturn(PETSC_SUCCESS);
296: vdraw = (PetscViewer_Draw *)v->data;
298: PetscCall(PetscFree(vdraw->drawtype));
299: PetscCall(PetscStrallocpy(drawtype, (char **)&vdraw->drawtype));
300: PetscFunctionReturn(PETSC_SUCCESS);
301: }
303: PetscErrorCode PetscViewerDrawGetDrawType(PetscViewer v, PetscDrawType *drawtype)
304: {
305: PetscViewer_Draw *vdraw;
306: PetscBool isdraw;
308: PetscFunctionBegin;
310: PetscCall(PetscObjectTypeCompare((PetscObject)v, PETSCVIEWERDRAW, &isdraw));
311: PetscCheck(isdraw, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Must be draw type PetscViewer");
312: vdraw = (PetscViewer_Draw *)v->data;
314: *drawtype = vdraw->drawtype;
315: PetscFunctionReturn(PETSC_SUCCESS);
316: }
318: PetscErrorCode PetscViewerDrawSetTitle(PetscViewer v, const char title[])
319: {
320: PetscViewer_Draw *vdraw;
321: PetscBool isdraw;
323: PetscFunctionBegin;
325: PetscCall(PetscObjectTypeCompare((PetscObject)v, PETSCVIEWERDRAW, &isdraw));
326: if (!isdraw) PetscFunctionReturn(PETSC_SUCCESS);
327: vdraw = (PetscViewer_Draw *)v->data;
329: PetscCall(PetscFree(vdraw->title));
330: PetscCall(PetscStrallocpy(title, &vdraw->title));
331: PetscFunctionReturn(PETSC_SUCCESS);
332: }
334: PetscErrorCode PetscViewerDrawGetTitle(PetscViewer v, const char *title[])
335: {
336: PetscViewer_Draw *vdraw;
337: PetscBool isdraw;
339: PetscFunctionBegin;
341: PetscCall(PetscObjectTypeCompare((PetscObject)v, PETSCVIEWERDRAW, &isdraw));
342: PetscCheck(isdraw, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Must be draw type PetscViewer");
343: vdraw = (PetscViewer_Draw *)v->data;
345: *title = vdraw->title;
346: PetscFunctionReturn(PETSC_SUCCESS);
347: }
349: /*@C
350: PetscViewerDrawOpen - Opens a `PetscDraw` window for use as a `PetscViewer` with type `PETSCVIEWERDRAW`. If you want to
351: do graphics in this window, you must call `PetscViewerDrawGetDraw()` and
352: perform the graphics on the `PetscDraw` object.
354: Collective
356: Input Parameters:
357: + comm - communicator that will share window
358: . display - the X display on which to open, or `NULL` for the local machine
359: . title - the title to put in the title bar, or `NULL` for no title
360: . x - horizonal screen coordinate of the upper left corner of window, or use `PETSC_DECIDE`
361: . y - vertical screen coordinate of the upper left corner of window, or use `PETSC_DECIDE`
362: . 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`
363: - 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`
365: Output Parameter:
366: . viewer - the `PetscViewer`
368: Format Options:
369: + `PETSC_VIEWER_DRAW_BASIC` - displays with basic format
370: - `PETSC_VIEWER_DRAW_LG` - displays using a line graph
372: Options Database Keys:
373: + -draw_type - use x or null
374: . -nox - Disables all x-windows output
375: . -display <name> - Specifies name of machine for the X display
376: . -geometry <x,y,w,h> - allows setting the window location and size
377: - -draw_pause <pause> - Sets time (in seconds) that the
378: program pauses after PetscDrawPause() has been called
379: (0 is default, -1 implies until user input).
381: Level: beginner
383: Fortran Note:
384: Whenever indicating null character data in a Fortran code,
385: `PETSC_NULL_CHARACTER` must be employed; using NULL is not
386: correct for character data! Thus, `PETSC_NULL_CHARACTER` can be
387: used for the display and title input parameters.
389: .seealso: [](sec_viewers), `PETSCVIEWERDRAW`, `PetscDrawCreate()`, `PetscViewerDestroy()`, `PetscViewerDrawGetDraw()`, `PetscViewerCreate()`, `PETSC_VIEWER_DRAW_`,
390: `PETSC_VIEWER_DRAW_WORLD`, `PETSC_VIEWER_DRAW_SELF`
391: @*/
392: PetscErrorCode PetscViewerDrawOpen(MPI_Comm comm, const char display[], const char title[], int x, int y, int w, int h, PetscViewer *viewer)
393: {
394: PetscFunctionBegin;
395: PetscCall(PetscViewerCreate(comm, viewer));
396: PetscCall(PetscViewerSetType(*viewer, PETSCVIEWERDRAW));
397: PetscCall(PetscViewerDrawSetInfo(*viewer, display, title, x, y, w, h));
398: PetscFunctionReturn(PETSC_SUCCESS);
399: }
401: #include <petsc/private/drawimpl.h>
403: PetscErrorCode PetscViewerGetSubViewer_Draw(PetscViewer viewer, MPI_Comm comm, PetscViewer *sviewer)
404: {
405: PetscMPIInt rank;
406: PetscInt i;
407: PetscViewer_Draw *vdraw = (PetscViewer_Draw *)viewer->data, *svdraw;
409: PetscFunctionBegin;
410: PetscCheck(!vdraw->singleton_made, PETSC_COMM_SELF, PETSC_ERR_ORDER, "Trying to get SubViewer without first restoring previous");
411: /* only processor zero can use the PetscViewer draw singleton */
412: if (sviewer) *sviewer = NULL;
413: PetscCallMPI(MPI_Comm_rank(PetscObjectComm((PetscObject)viewer), &rank));
414: if (rank == 0) {
415: PetscMPIInt flg;
416: PetscDraw draw, sdraw;
418: PetscCallMPI(MPI_Comm_compare(PETSC_COMM_SELF, comm, &flg));
419: PetscCheck(flg == MPI_IDENT || flg == MPI_CONGRUENT, PETSC_COMM_SELF, PETSC_ERR_SUP, "PetscViewerGetSubViewer() for PETSCVIEWERDRAW requires a singleton MPI_Comm");
420: PetscCall(PetscViewerCreate(comm, sviewer));
421: PetscCall(PetscViewerSetType(*sviewer, PETSCVIEWERDRAW));
422: svdraw = (PetscViewer_Draw *)(*sviewer)->data;
423: (*sviewer)->format = viewer->format;
424: for (i = 0; i < vdraw->draw_max; i++) { /* XXX this is wrong if svdraw->draw_max (initially 5) < vdraw->draw_max */
425: if (vdraw->draw[i]) PetscCall(PetscDrawGetSingleton(vdraw->draw[i], &svdraw->draw[i]));
426: }
427: PetscCall(PetscViewerDrawGetDraw(viewer, 0, &draw));
428: PetscCall(PetscViewerDrawGetDraw(*sviewer, 0, &sdraw));
429: if (draw->savefilename) {
430: PetscCall(PetscDrawSetSave(sdraw, draw->savefilename));
431: sdraw->savefilecount = draw->savefilecount;
432: sdraw->savesinglefile = draw->savesinglefile;
433: sdraw->savemoviefps = draw->savemoviefps;
434: sdraw->saveonclear = draw->saveonclear;
435: sdraw->saveonflush = draw->saveonflush;
436: }
437: if (draw->savefinalfilename) PetscCall(PetscDrawSetSaveFinalImage(sdraw, draw->savefinalfilename));
438: } else {
439: PetscDraw draw;
440: PetscCall(PetscViewerDrawGetDraw(viewer, 0, &draw));
441: }
442: vdraw->singleton_made = PETSC_TRUE;
443: PetscFunctionReturn(PETSC_SUCCESS);
444: }
446: PetscErrorCode PetscViewerRestoreSubViewer_Draw(PetscViewer viewer, MPI_Comm comm, PetscViewer *sviewer)
447: {
448: PetscMPIInt rank;
449: PetscInt i;
450: PetscViewer_Draw *vdraw = (PetscViewer_Draw *)viewer->data, *svdraw;
452: PetscFunctionBegin;
453: PetscCheck(vdraw->singleton_made, PETSC_COMM_SELF, PETSC_ERR_ORDER, "Trying to restore a singleton that was not gotten");
454: PetscCallMPI(MPI_Comm_rank(PetscObjectComm((PetscObject)viewer), &rank));
455: if (rank == 0) {
456: PetscDraw draw, sdraw;
458: PetscCall(PetscViewerDrawGetDraw(viewer, 0, &draw));
459: PetscCall(PetscViewerDrawGetDraw(*sviewer, 0, &sdraw));
460: if (draw->savefilename) {
461: draw->savefilecount = sdraw->savefilecount;
462: PetscCallMPI(MPI_Bcast(&draw->savefilecount, 1, MPIU_INT, 0, PetscObjectComm((PetscObject)draw)));
463: }
464: svdraw = (PetscViewer_Draw *)(*sviewer)->data;
465: for (i = 0; i < vdraw->draw_max; i++) {
466: if (vdraw->draw[i] && svdraw->draw[i]) PetscCall(PetscDrawRestoreSingleton(vdraw->draw[i], &svdraw->draw[i]));
467: }
468: PetscCall(PetscFree3(svdraw->draw, svdraw->drawlg, svdraw->drawaxis));
469: PetscCall(PetscFree((*sviewer)->data));
470: PetscCall(PetscHeaderDestroy(sviewer));
471: } else {
472: PetscDraw draw;
474: PetscCall(PetscViewerDrawGetDraw(viewer, 0, &draw));
475: if (draw->savefilename) PetscCallMPI(MPI_Bcast(&draw->savefilecount, 1, MPIU_INT, 0, PetscObjectComm((PetscObject)draw)));
476: }
478: vdraw->singleton_made = PETSC_FALSE;
479: PetscFunctionReturn(PETSC_SUCCESS);
480: }
482: PetscErrorCode PetscViewerSetFromOptions_Draw(PetscViewer v, PetscOptionItems *PetscOptionsObject)
483: {
484: PetscReal bounds[16];
485: PetscInt nbounds = 16;
486: PetscBool flg;
488: PetscFunctionBegin;
489: PetscOptionsHeadBegin(PetscOptionsObject, "Draw PetscViewer Options");
490: PetscCall(PetscOptionsRealArray("-draw_bounds", "Bounds to put on plots axis", "PetscViewerDrawSetBounds", bounds, &nbounds, &flg));
491: if (flg) PetscCall(PetscViewerDrawSetBounds(v, nbounds / 2, bounds));
492: PetscOptionsHeadEnd();
493: PetscFunctionReturn(PETSC_SUCCESS);
494: }
496: PetscErrorCode PetscViewerView_Draw(PetscViewer viewer, PetscViewer v)
497: {
498: PetscDraw draw;
499: PetscInt i;
500: PetscViewer_Draw *vdraw = (PetscViewer_Draw *)viewer->data;
501: PetscBool iascii;
503: PetscFunctionBegin;
504: PetscCall(PetscObjectTypeCompare((PetscObject)v, PETSCVIEWERASCII, &iascii));
505: if (iascii) PetscCall(PetscViewerASCIIPrintf(v, "Draw viewer is of type %s\n", vdraw->drawtype));
506: /* If the PetscViewer has just been created then no vdraw->draw yet
507: exists so this will not actually call the viewer on any draws. */
508: for (i = 0; i < vdraw->draw_base; i++) {
509: if (vdraw->draw[i]) {
510: PetscCall(PetscViewerDrawGetDraw(viewer, i, &draw));
511: PetscCall(PetscDrawView(draw, v));
512: }
513: }
514: PetscFunctionReturn(PETSC_SUCCESS);
515: }
517: /*MC
518: PETSCVIEWERDRAW - A viewer that generates graphics, either to the screen or a file
520: Level: beginner
522: .seealso: [](sec_viewers), `PetscViewerDrawOpen()`, `PetscViewerDrawGetDraw()`, `PETSC_VIEWER_DRAW_()`, `PETSC_VIEWER_DRAW_SELF`, `PETSC_VIEWER_DRAW_WORLD`,
523: `PetscViewerCreate()`, `PetscViewerASCIIOpen()`, `PetscViewerBinaryOpen()`, `PETSCVIEWERBINARY`,
524: `PetscViewerMatlabOpen()`, `VecView()`, `DMView()`, `PetscViewerMatlabPutArray()`, `PETSCVIEWERASCII`, `PETSCVIEWERMATLAB`,
525: `PetscViewerFileSetName()`, `PetscViewerFileSetMode()`, `PetscViewerFormat`, `PetscViewerType`, `PetscViewerSetType()`
526: M*/
527: PETSC_EXTERN PetscErrorCode PetscViewerCreate_Draw(PetscViewer viewer)
528: {
529: PetscViewer_Draw *vdraw;
531: PetscFunctionBegin;
532: PetscCall(PetscNew(&vdraw));
533: viewer->data = (void *)vdraw;
535: viewer->ops->flush = PetscViewerFlush_Draw;
536: viewer->ops->view = PetscViewerView_Draw;
537: viewer->ops->destroy = PetscViewerDestroy_Draw;
538: viewer->ops->setfromoptions = PetscViewerSetFromOptions_Draw;
539: viewer->ops->getsubviewer = PetscViewerGetSubViewer_Draw;
540: viewer->ops->restoresubviewer = PetscViewerRestoreSubViewer_Draw;
542: /* these are created on the fly if requested */
543: vdraw->draw_max = 5;
544: vdraw->draw_base = 0;
545: vdraw->w = PETSC_DECIDE;
546: vdraw->h = PETSC_DECIDE;
548: PetscCall(PetscCalloc3(vdraw->draw_max, &vdraw->draw, vdraw->draw_max, &vdraw->drawlg, vdraw->draw_max, &vdraw->drawaxis));
549: vdraw->singleton_made = PETSC_FALSE;
550: PetscFunctionReturn(PETSC_SUCCESS);
551: }
553: /*@
554: PetscViewerDrawClear - Clears a `PetscDraw` graphic associated with a `PetscViewer`.
556: Not Collective
558: Input Parameter:
559: . viewer - the `PetscViewer`
561: Level: intermediate
563: .seealso: [](sec_viewers), `PETSCVIEWERDRAW`, `PetscViewerDrawOpen()`, `PetscViewerDrawGetDraw()`,
564: @*/
565: PetscErrorCode PetscViewerDrawClear(PetscViewer viewer)
566: {
567: PetscViewer_Draw *vdraw;
568: PetscBool isdraw;
569: PetscInt i;
571: PetscFunctionBegin;
573: PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERDRAW, &isdraw));
574: if (!isdraw) PetscFunctionReturn(PETSC_SUCCESS);
575: vdraw = (PetscViewer_Draw *)viewer->data;
577: for (i = 0; i < vdraw->draw_max; i++) {
578: if (vdraw->draw[i]) PetscCall(PetscDrawClear(vdraw->draw[i]));
579: }
580: PetscFunctionReturn(PETSC_SUCCESS);
581: }
583: /*@
584: PetscViewerDrawGetPause - Gets the pause value (how long to pause before an image is changed) in the `PETSCVIEWERDRAW` `PetscViewer`
586: Not Collective
588: Input Parameter:
589: . viewer - the `PetscViewer`
591: Output Parameter:
592: . pause - the pause value
594: Level: intermediate
596: .seealso: [](sec_viewers), `PETSCVIEWERDRAW`, `PetscViewerDrawOpen()`, `PetscViewerDrawGetDraw()`,
597: @*/
598: PetscErrorCode PetscViewerDrawGetPause(PetscViewer viewer, PetscReal *pause)
599: {
600: PetscViewer_Draw *vdraw;
601: PetscBool isdraw;
602: PetscInt i;
603: PetscDraw draw;
605: PetscFunctionBegin;
607: PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERDRAW, &isdraw));
608: if (!isdraw) {
609: *pause = 0.0;
610: PetscFunctionReturn(PETSC_SUCCESS);
611: }
612: vdraw = (PetscViewer_Draw *)viewer->data;
614: for (i = 0; i < vdraw->draw_max; i++) {
615: if (vdraw->draw[i]) {
616: PetscCall(PetscDrawGetPause(vdraw->draw[i], pause));
617: PetscFunctionReturn(PETSC_SUCCESS);
618: }
619: }
620: /* none exist yet so create one and get its pause */
621: PetscCall(PetscViewerDrawGetDraw(viewer, 0, &draw));
622: PetscCall(PetscDrawGetPause(draw, pause));
623: PetscFunctionReturn(PETSC_SUCCESS);
624: }
626: /*@
627: PetscViewerDrawSetPause - Sets a pause for each `PetscDraw` in the `PETSCVIEWERDRAW` `PetscViewer`
629: Not Collective
631: Input Parameters:
632: + viewer - the `PetscViewer`
633: - pause - the pause value
635: Level: intermediate
637: .seealso: [](sec_viewers), `PETSCVIEWERDRAW`, `PetscViewerDrawOpen()`, `PetscViewerDrawGetDraw()`,
638: @*/
639: PetscErrorCode PetscViewerDrawSetPause(PetscViewer viewer, PetscReal pause)
640: {
641: PetscViewer_Draw *vdraw;
642: PetscBool isdraw;
643: PetscInt i;
645: PetscFunctionBegin;
647: PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERDRAW, &isdraw));
648: if (!isdraw) PetscFunctionReturn(PETSC_SUCCESS);
649: vdraw = (PetscViewer_Draw *)viewer->data;
651: vdraw->pause = pause;
652: for (i = 0; i < vdraw->draw_max; i++) {
653: if (vdraw->draw[i]) PetscCall(PetscDrawSetPause(vdraw->draw[i], pause));
654: }
655: PetscFunctionReturn(PETSC_SUCCESS);
656: }
658: /*@
659: PetscViewerDrawSetHold - Holds previous image when drawing new image
661: Not Collective
663: Input Parameters:
664: + viewer - the `PetscViewer`
665: - hold - `PETSC_TRUE` indicates to hold the previous image
667: Level: intermediate
669: .seealso: [](sec_viewers), `PETSCVIEWERDRAW`, `PetscViewerDrawOpen()`, `PetscViewerDrawGetDraw()`,
670: @*/
671: PetscErrorCode PetscViewerDrawSetHold(PetscViewer viewer, PetscBool hold)
672: {
673: PetscViewer_Draw *vdraw;
674: PetscBool isdraw;
676: PetscFunctionBegin;
678: PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERDRAW, &isdraw));
679: if (!isdraw) PetscFunctionReturn(PETSC_SUCCESS);
680: vdraw = (PetscViewer_Draw *)viewer->data;
682: vdraw->hold = hold;
683: PetscFunctionReturn(PETSC_SUCCESS);
684: }
686: /*@
687: PetscViewerDrawGetHold - Checks if the `PETSCVIEWERDRAW` `PetscViewer` holds previous image when drawing new image
689: Not Collective
691: Input Parameter:
692: . viewer - the `PetscViewer`
694: Output Parameter:
695: . hold - indicates to hold or not
697: Level: intermediate
699: .seealso: [](sec_viewers), `PETSCVIEWERDRAW`, `PetscViewerDrawOpen()`, `PetscViewerDrawGetDraw()`,
700: @*/
701: PetscErrorCode PetscViewerDrawGetHold(PetscViewer viewer, PetscBool *hold)
702: {
703: PetscViewer_Draw *vdraw;
704: PetscBool isdraw;
706: PetscFunctionBegin;
708: PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERDRAW, &isdraw));
709: if (!isdraw) {
710: *hold = PETSC_FALSE;
711: PetscFunctionReturn(PETSC_SUCCESS);
712: }
713: vdraw = (PetscViewer_Draw *)viewer->data;
715: *hold = vdraw->hold;
716: PetscFunctionReturn(PETSC_SUCCESS);
717: }
719: /*
720: The variable Petsc_Viewer_Draw_keyval is used to indicate an MPI attribute that
721: is attached to a communicator, in this case the attribute is a PetscViewer.
722: */
723: PetscMPIInt Petsc_Viewer_Draw_keyval = MPI_KEYVAL_INVALID;
725: /*@C
726: PETSC_VIEWER_DRAW_ - Creates a window `PETSCVIEWERDRAW` `PetscViewer` shared by all processors
727: in a communicator.
729: Collective
731: Input Parameter:
732: . comm - the MPI communicator to share the window `PetscViewer`
734: Level: intermediate
736: Note:
737: Unlike almost all other PETSc routines, `PETSC_VIEWER_DRAW_()` does not return
738: an error code. The window is usually used in the form
739: $ XXXView(XXX object,PETSC_VIEWER_DRAW_(comm));
741: .seealso: [](sec_viewers), `PETSCVIEWERDRAW`, `PetscViewer`, `PETSC_VIEWER_DRAW_WORLD`, `PETSC_VIEWER_DRAW_SELF`, `PetscViewerDrawOpen()`,
742: @*/
743: PetscViewer PETSC_VIEWER_DRAW_(MPI_Comm comm)
744: {
745: PetscErrorCode ierr;
746: PetscMPIInt flag, mpi_ierr;
747: PetscViewer viewer;
748: MPI_Comm ncomm;
750: PetscFunctionBegin;
751: ierr = PetscCommDuplicate(comm, &ncomm, NULL);
752: if (ierr) {
753: ierr = PetscError(PETSC_COMM_SELF, __LINE__, "PETSC_VIEWER_DRAW_", __FILE__, PETSC_ERR_PLIB, PETSC_ERROR_INITIAL, " ");
754: PetscFunctionReturn(NULL);
755: }
756: if (Petsc_Viewer_Draw_keyval == MPI_KEYVAL_INVALID) {
757: mpi_ierr = MPI_Comm_create_keyval(MPI_COMM_NULL_COPY_FN, MPI_COMM_NULL_DELETE_FN, &Petsc_Viewer_Draw_keyval, NULL);
758: if (mpi_ierr) {
759: ierr = PetscError(PETSC_COMM_SELF, __LINE__, "PETSC_VIEWER_DRAW_", __FILE__, PETSC_ERR_PLIB, PETSC_ERROR_INITIAL, " ");
760: PetscFunctionReturn(NULL);
761: }
762: }
763: mpi_ierr = MPI_Comm_get_attr(ncomm, Petsc_Viewer_Draw_keyval, (void **)&viewer, &flag);
764: if (mpi_ierr) {
765: ierr = PetscError(PETSC_COMM_SELF, __LINE__, "PETSC_VIEWER_DRAW_", __FILE__, PETSC_ERR_PLIB, PETSC_ERROR_INITIAL, " ");
766: PetscFunctionReturn(NULL);
767: }
768: if (!flag) { /* PetscViewer not yet created */
769: ierr = PetscViewerDrawOpen(ncomm, NULL, NULL, PETSC_DECIDE, PETSC_DECIDE, 300, 300, &viewer);
770: if (ierr) {
771: ierr = PetscError(PETSC_COMM_SELF, __LINE__, "PETSC_VIEWER_DRAW_", __FILE__, PETSC_ERR_PLIB, PETSC_ERROR_REPEAT, " ");
772: PetscFunctionReturn(NULL);
773: }
774: ierr = PetscObjectRegisterDestroy((PetscObject)viewer);
775: if (ierr) {
776: ierr = PetscError(PETSC_COMM_SELF, __LINE__, "PETSC_VIEWER_DRAW_", __FILE__, PETSC_ERR_PLIB, PETSC_ERROR_REPEAT, " ");
777: PetscFunctionReturn(NULL);
778: }
779: mpi_ierr = MPI_Comm_set_attr(ncomm, Petsc_Viewer_Draw_keyval, (void *)viewer);
780: if (mpi_ierr) {
781: ierr = PetscError(PETSC_COMM_SELF, __LINE__, "PETSC_VIEWER_DRAW_", __FILE__, PETSC_ERR_PLIB, PETSC_ERROR_INITIAL, " ");
782: PetscFunctionReturn(NULL);
783: }
784: }
785: ierr = PetscCommDestroy(&ncomm);
786: if (ierr) {
787: ierr = PetscError(PETSC_COMM_SELF, __LINE__, "PETSC_VIEWER_DRAW_", __FILE__, PETSC_ERR_PLIB, PETSC_ERROR_REPEAT, " ");
788: PetscFunctionReturn(NULL);
789: }
790: PetscFunctionReturn(viewer);
791: }
793: /*@
794: PetscViewerDrawSetBounds - sets the upper and lower bounds to be used in plotting
796: Collective
798: Input Parameters:
799: + viewer - the Petsc`Viewer` (created with `PetscViewerDrawOpen()`)
800: . nbounds - number of plots that can be made with this viewer, for example the dof passed to `DMDACreate()`
801: - 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, .....
803: Options Database Key:
804: . -draw_bounds minF0,maxF0,minF1,maxF1 - the lower left and upper right bounds
806: Level: intermediate
808: Note:
809: 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
810: 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
811: this viewer. Otherwise the color to physical value meaning changes with each new image if this is not set.
813: .seealso: [](sec_viewers), `PETSCVIEWERDRAW`, `PetscViewerDrawGetLG()`, `PetscViewerDrawGetAxis()`, `PetscViewerDrawOpen()`
814: @*/
815: PetscErrorCode PetscViewerDrawSetBounds(PetscViewer viewer, PetscInt nbounds, const PetscReal *bounds)
816: {
817: PetscViewer_Draw *vdraw;
818: PetscBool isdraw;
820: PetscFunctionBegin;
822: PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERDRAW, &isdraw));
823: if (!isdraw) PetscFunctionReturn(PETSC_SUCCESS);
824: vdraw = (PetscViewer_Draw *)viewer->data;
826: vdraw->nbounds = nbounds;
827: PetscCall(PetscFree(vdraw->bounds));
828: PetscCall(PetscMalloc1(2 * nbounds, &vdraw->bounds));
829: PetscCall(PetscArraycpy(vdraw->bounds, bounds, 2 * nbounds));
830: PetscFunctionReturn(PETSC_SUCCESS);
831: }
833: /*@C
834: PetscViewerDrawGetBounds - gets the upper and lower bounds to be used in plotting set with `PetscViewerDrawSetBounds()`
836: Collective
838: Input Parameter:
839: . viewer - the `PetscViewer` (created with `PetscViewerDrawOpen()`)
841: Output Parameters:
842: + nbounds - number of plots that can be made with this viewer, for example the dof passed to `DMDACreate()`
843: - 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, .....
845: Level: intermediate
847: .seealso: [](sec_viewers), `PETSCVIEWERDRAW`, `PetscViewerDrawGetLG()`, `PetscViewerDrawGetAxis()`, `PetscViewerDrawOpen()`, `PetscViewerDrawSetBounds()`
848: @*/
849: PetscErrorCode PetscViewerDrawGetBounds(PetscViewer viewer, PetscInt *nbounds, const PetscReal **bounds)
850: {
851: PetscViewer_Draw *vdraw;
852: PetscBool isdraw;
854: PetscFunctionBegin;
856: PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERDRAW, &isdraw));
857: if (!isdraw) {
858: if (nbounds) *nbounds = 0;
859: if (bounds) *bounds = NULL;
860: PetscFunctionReturn(PETSC_SUCCESS);
861: }
862: vdraw = (PetscViewer_Draw *)viewer->data;
864: if (nbounds) *nbounds = vdraw->nbounds;
865: if (bounds) *bounds = vdraw->bounds;
866: PetscFunctionReturn(PETSC_SUCCESS);
867: }