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: /*@
38: PetscViewerDrawBaseAdd - add to the base integer that is added to the `windownumber` passed to `PetscViewerDrawGetDraw()`
40: Logically Collective
42: Input Parameters:
43: + viewer - the `PetscViewer` (created with `PetscViewerDrawOpen()`)
44: - windownumber - how much to add to the base
46: Level: developer
48: Note:
49: A `PETSCVIEWERDRAW` may have multiple `PetscDraw` subwindows, this increases the number of the subwindow that is returned with `PetscViewerDrawGetDraw()`
51: .seealso: [](sec_viewers), `PetscViewerDrawGetLG()`, `PetscViewerDrawGetAxis()`, `PetscViewerDrawOpen()`, `PetscViewerDrawGetDraw()`, `PetscViewerDrawBaseSet()`
52: @*/
53: PetscErrorCode PetscViewerDrawBaseAdd(PetscViewer viewer, PetscInt windownumber)
54: {
55: PetscViewer_Draw *vdraw;
56: PetscBool isdraw;
58: PetscFunctionBegin;
61: PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERDRAW, &isdraw));
62: PetscCheck(isdraw, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Must be draw type PetscViewer");
63: vdraw = (PetscViewer_Draw *)viewer->data;
65: PetscCheck(windownumber + vdraw->draw_base >= 0, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Resulting base %" PetscInt_FMT " cannot be negative", windownumber + vdraw->draw_base);
66: vdraw->draw_base += windownumber;
67: PetscFunctionReturn(PETSC_SUCCESS);
68: }
70: /*@
71: PetscViewerDrawBaseSet - sets the base integer that is added to the `windownumber` passed to `PetscViewerDrawGetDraw()`
73: Logically Collective
75: Input Parameters:
76: + viewer - the `PetscViewer` (created with `PetscViewerDrawOpen()`)
77: - windownumber - value to set the base
79: Level: developer
81: Note:
82: A `PETSCVIEWERDRAW` may have multiple `PetscDraw` subwindows, this increases the number of the subwindow that is returned with `PetscViewerDrawGetDraw()`
84: .seealso: [](sec_viewers), `PetscViewerDrawGetLG()`, `PetscViewerDrawGetAxis()`, `PetscViewerDrawOpen()`, `PetscViewerDrawGetDraw()`, `PetscViewerDrawBaseAdd()`
85: @*/
86: PetscErrorCode PetscViewerDrawBaseSet(PetscViewer viewer, PetscInt windownumber)
87: {
88: PetscViewer_Draw *vdraw;
89: PetscBool isdraw;
91: PetscFunctionBegin;
94: PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERDRAW, &isdraw));
95: PetscCheck(isdraw, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Must be draw type PetscViewer");
96: vdraw = (PetscViewer_Draw *)viewer->data;
98: PetscCheck(windownumber >= 0, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Resulting base %" PetscInt_FMT " cannot be negative", windownumber);
99: vdraw->draw_base = windownumber;
100: PetscFunctionReturn(PETSC_SUCCESS);
101: }
103: PetscErrorCode PetscViewerDrawResize(PetscViewer v, int w, int h)
104: {
105: PetscViewer_Draw *vdraw;
106: PetscBool isdraw;
108: PetscFunctionBegin;
110: PetscCall(PetscObjectTypeCompare((PetscObject)v, PETSCVIEWERDRAW, &isdraw));
111: if (!isdraw) PetscFunctionReturn(PETSC_SUCCESS);
112: vdraw = (PetscViewer_Draw *)v->data;
114: if (w >= 1) vdraw->w = w;
115: if (h >= 1) vdraw->h = h;
116: PetscFunctionReturn(PETSC_SUCCESS);
117: }
119: PetscErrorCode PetscViewerDrawSetInfo(PetscViewer v, const char display[], const char title[], int x, int y, int w, int h)
120: {
121: PetscViewer_Draw *vdraw;
122: PetscBool isdraw;
124: PetscFunctionBegin;
126: PetscCall(PetscObjectTypeCompare((PetscObject)v, PETSCVIEWERDRAW, &isdraw));
127: if (!isdraw) PetscFunctionReturn(PETSC_SUCCESS);
128: vdraw = (PetscViewer_Draw *)v->data;
130: PetscCall(PetscStrallocpy(display, &vdraw->display));
131: PetscCall(PetscStrallocpy(title, &vdraw->title));
132: if (w >= 1) vdraw->w = w;
133: if (h >= 1) vdraw->h = h;
134: PetscFunctionReturn(PETSC_SUCCESS);
135: }
137: PetscErrorCode PetscViewerDrawSetTitle(PetscViewer v, const char title[])
138: {
139: PetscViewer_Draw *vdraw;
140: PetscBool isdraw;
142: PetscFunctionBegin;
144: PetscCall(PetscObjectTypeCompare((PetscObject)v, PETSCVIEWERDRAW, &isdraw));
145: if (!isdraw) PetscFunctionReturn(PETSC_SUCCESS);
146: vdraw = (PetscViewer_Draw *)v->data;
148: PetscCall(PetscFree(vdraw->title));
149: PetscCall(PetscStrallocpy(title, &vdraw->title));
150: PetscFunctionReturn(PETSC_SUCCESS);
151: }
153: PetscErrorCode PetscViewerDrawGetTitle(PetscViewer v, const char *title[])
154: {
155: PetscViewer_Draw *vdraw;
156: PetscBool isdraw;
158: PetscFunctionBegin;
160: PetscCall(PetscObjectTypeCompare((PetscObject)v, PETSCVIEWERDRAW, &isdraw));
161: PetscCheck(isdraw, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Must be draw type PetscViewer");
162: vdraw = (PetscViewer_Draw *)v->data;
164: *title = vdraw->title;
165: PetscFunctionReturn(PETSC_SUCCESS);
166: }
168: /*@
169: PetscViewerDrawOpen - Opens a `PetscDraw` window for use as a `PetscViewer` with type
170: `PETSCVIEWERDRAW`.
172: Collective
174: Input Parameters:
175: + comm - communicator that will share window
176: . display - the X display on which to open, or `NULL` for the local machine
177: . title - the title to put in the title bar, or `NULL` for no title
178: . x - horizontal screen coordinate of the upper left corner of window, or use `PETSC_DECIDE`
179: . y - vertical screen coordinate of the upper left corner of window, or use `PETSC_DECIDE`
180: . 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`
181: - 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`
183: Output Parameter:
184: . viewer - the `PetscViewer`
186: Options Database Keys:
187: + -draw_type - use x or null
188: . -nox - Disables all x-windows output
189: . -display <name> - Specifies name of machine for the X display
190: . -geometry <x,y,w,h> - allows setting the window location and size
191: - -draw_pause <pause> - Sets time (in seconds) that the
192: program pauses after PetscDrawPause() has been called
193: (0 is default, -1 implies until user input).
195: Level: beginner
197: Notes:
198: If you want to do graphics in this window, you must call `PetscViewerDrawGetDraw()` and
199: perform the graphics on the `PetscDraw` object.
201: Format options include\:
202: + `PETSC_VIEWER_DRAW_BASIC` - displays with basic format
203: - `PETSC_VIEWER_DRAW_LG` - displays using a line graph
205: Fortran Notes:
206: Whenever indicating null character data in a Fortran code,
207: `PETSC_NULL_CHARACTER` must be employed; using NULL is not
208: correct for character data! Thus, `PETSC_NULL_CHARACTER` can be
209: used for the display and title input parameters.
211: .seealso: [](sec_viewers), `PETSCVIEWERDRAW`, `PetscDrawCreate()`, `PetscViewerDestroy()`, `PetscViewerDrawGetDraw()`, `PetscViewerCreate()`, `PETSC_VIEWER_DRAW_`,
212: `PETSC_VIEWER_DRAW_WORLD`, `PETSC_VIEWER_DRAW_SELF`
213: @*/
214: PetscErrorCode PetscViewerDrawOpen(MPI_Comm comm, const char display[], const char title[], int x, int y, int w, int h, PetscViewer *viewer)
215: {
216: PetscFunctionBegin;
217: PetscCall(PetscViewerCreate(comm, viewer));
218: PetscCall(PetscViewerSetType(*viewer, PETSCVIEWERDRAW));
219: PetscCall(PetscViewerDrawSetInfo(*viewer, display, title, x, y, w, h));
220: PetscFunctionReturn(PETSC_SUCCESS);
221: }
223: #include <petsc/private/drawimpl.h>
225: static PetscErrorCode PetscViewerGetSubViewer_Draw(PetscViewer viewer, MPI_Comm comm, PetscViewer *sviewer)
226: {
227: PetscMPIInt rank;
228: PetscInt i;
229: PetscViewer_Draw *vdraw = (PetscViewer_Draw *)viewer->data, *svdraw;
231: PetscFunctionBegin;
232: PetscCheck(!vdraw->singleton_made, PETSC_COMM_SELF, PETSC_ERR_ORDER, "Trying to get SubViewer without first restoring previous");
233: /* only processor zero can use the PetscViewer draw singleton */
234: PetscCallMPI(MPI_Comm_rank(PetscObjectComm((PetscObject)viewer), &rank));
235: if (rank == 0) {
236: PetscMPIInt flg;
237: PetscDraw draw, sdraw;
239: PetscCallMPI(MPI_Comm_compare(PETSC_COMM_SELF, comm, &flg));
240: PetscCheck(flg == MPI_IDENT || flg == MPI_CONGRUENT, PETSC_COMM_SELF, PETSC_ERR_SUP, "PetscViewerGetSubViewer() for PETSCVIEWERDRAW requires a singleton MPI_Comm");
241: PetscCall(PetscViewerCreate(comm, sviewer));
242: PetscCall(PetscViewerSetType(*sviewer, PETSCVIEWERDRAW));
243: svdraw = (PetscViewer_Draw *)(*sviewer)->data;
244: (*sviewer)->format = viewer->format;
245: for (i = 0; i < vdraw->draw_max; i++) { /* XXX this is wrong if svdraw->draw_max (initially 5) < vdraw->draw_max */
246: if (vdraw->draw[i]) PetscCall(PetscDrawGetSingleton(vdraw->draw[i], &svdraw->draw[i]));
247: }
248: PetscCall(PetscViewerDrawGetDraw(viewer, 0, &draw));
249: PetscCall(PetscViewerDrawGetDraw(*sviewer, 0, &sdraw));
250: if (draw->savefilename) {
251: PetscCall(PetscDrawSetSave(sdraw, draw->savefilename));
252: sdraw->savefilecount = draw->savefilecount;
253: sdraw->savesinglefile = draw->savesinglefile;
254: sdraw->savemoviefps = draw->savemoviefps;
255: sdraw->saveonclear = draw->saveonclear;
256: sdraw->saveonflush = draw->saveonflush;
257: }
258: if (draw->savefinalfilename) PetscCall(PetscDrawSetSaveFinalImage(sdraw, draw->savefinalfilename));
259: } else {
260: PetscDraw draw;
261: PetscCall(PetscViewerDrawGetDraw(viewer, 0, &draw));
262: }
263: vdraw->singleton_made = PETSC_TRUE;
264: PetscFunctionReturn(PETSC_SUCCESS);
265: }
267: static PetscErrorCode PetscViewerRestoreSubViewer_Draw(PetscViewer viewer, MPI_Comm comm, PetscViewer *sviewer)
268: {
269: PetscMPIInt rank;
270: PetscInt i;
271: PetscViewer_Draw *vdraw = (PetscViewer_Draw *)viewer->data, *svdraw;
273: PetscFunctionBegin;
274: PetscCheck(vdraw->singleton_made, PETSC_COMM_SELF, PETSC_ERR_ORDER, "Trying to restore a singleton that was not gotten");
275: PetscCallMPI(MPI_Comm_rank(PetscObjectComm((PetscObject)viewer), &rank));
276: if (rank == 0) {
277: PetscDraw draw, sdraw;
279: PetscCall(PetscViewerDrawGetDraw(viewer, 0, &draw));
280: PetscCall(PetscViewerDrawGetDraw(*sviewer, 0, &sdraw));
281: if (draw->savefilename) {
282: draw->savefilecount = sdraw->savefilecount;
283: PetscCallMPI(MPI_Bcast(&draw->savefilecount, 1, MPIU_INT, 0, PetscObjectComm((PetscObject)draw)));
284: }
285: svdraw = (PetscViewer_Draw *)(*sviewer)->data;
286: for (i = 0; i < vdraw->draw_max; i++) {
287: if (vdraw->draw[i] && svdraw->draw[i]) PetscCall(PetscDrawRestoreSingleton(vdraw->draw[i], &svdraw->draw[i]));
288: }
289: PetscCall(PetscFree3(svdraw->draw, svdraw->drawlg, svdraw->drawaxis));
290: PetscCall(PetscFree((*sviewer)->data));
291: PetscCall(PetscHeaderDestroy(sviewer));
292: } else {
293: PetscDraw draw;
295: PetscCall(PetscViewerDrawGetDraw(viewer, 0, &draw));
296: if (draw->savefilename) PetscCallMPI(MPI_Bcast(&draw->savefilecount, 1, MPIU_INT, 0, PetscObjectComm((PetscObject)draw)));
297: }
299: vdraw->singleton_made = PETSC_FALSE;
300: PetscFunctionReturn(PETSC_SUCCESS);
301: }
303: static PetscErrorCode PetscViewerSetFromOptions_Draw(PetscViewer v, PetscOptionItems PetscOptionsObject)
304: {
305: PetscReal bounds[16];
306: PetscInt nbounds = 16;
307: PetscBool flg;
309: PetscFunctionBegin;
310: PetscOptionsHeadBegin(PetscOptionsObject, "Draw PetscViewer Options");
311: PetscCall(PetscOptionsRealArray("-draw_bounds", "Bounds to put on plots axis", "PetscViewerDrawSetBounds", bounds, &nbounds, &flg));
312: if (flg) PetscCall(PetscViewerDrawSetBounds(v, nbounds / 2, bounds));
313: PetscOptionsHeadEnd();
314: PetscFunctionReturn(PETSC_SUCCESS);
315: }
317: static PetscErrorCode PetscViewerView_Draw(PetscViewer viewer, PetscViewer v)
318: {
319: PetscDraw draw;
320: PetscInt i;
321: PetscViewer_Draw *vdraw = (PetscViewer_Draw *)viewer->data;
322: PetscBool iascii;
324: PetscFunctionBegin;
325: PetscCall(PetscObjectTypeCompare((PetscObject)v, PETSCVIEWERASCII, &iascii));
326: if (iascii) PetscCall(PetscViewerASCIIPrintf(v, "Draw viewer is of type %s\n", vdraw->drawtype));
327: /* If the PetscViewer has just been created then no vdraw->draw yet
328: exists so this will not actually call the viewer on any draws. */
329: for (i = 0; i < vdraw->draw_base; i++) {
330: if (vdraw->draw[i]) {
331: PetscCall(PetscViewerDrawGetDraw(viewer, i, &draw));
332: PetscCall(PetscDrawView(draw, v));
333: }
334: }
335: PetscFunctionReturn(PETSC_SUCCESS);
336: }
338: /*MC
339: PETSCVIEWERDRAW - A viewer that generates graphics, either to the screen or a file
341: Level: beginner
343: .seealso: [](sec_viewers), `PetscViewerDrawOpen()`, `PetscViewerDrawGetDraw()`, `PETSC_VIEWER_DRAW_()`, `PETSC_VIEWER_DRAW_SELF`, `PETSC_VIEWER_DRAW_WORLD`,
344: `PetscViewerCreate()`, `PetscViewerASCIIOpen()`, `PetscViewerBinaryOpen()`, `PETSCVIEWERBINARY`,
345: `PetscViewerMatlabOpen()`, `VecView()`, `DMView()`, `PetscViewerMatlabPutArray()`, `PETSCVIEWERASCII`, `PETSCVIEWERMATLAB`,
346: `PetscViewerFileSetName()`, `PetscViewerFileSetMode()`, `PetscViewerFormat`, `PetscViewerType`, `PetscViewerSetType()`
347: M*/
348: PETSC_EXTERN PetscErrorCode PetscViewerCreate_Draw(PetscViewer viewer)
349: {
350: PetscViewer_Draw *vdraw;
352: PetscFunctionBegin;
353: PetscCall(PetscNew(&vdraw));
354: viewer->data = (void *)vdraw;
356: viewer->ops->flush = PetscViewerFlush_Draw;
357: viewer->ops->view = PetscViewerView_Draw;
358: viewer->ops->destroy = PetscViewerDestroy_Draw;
359: viewer->ops->setfromoptions = PetscViewerSetFromOptions_Draw;
360: viewer->ops->getsubviewer = PetscViewerGetSubViewer_Draw;
361: viewer->ops->restoresubviewer = PetscViewerRestoreSubViewer_Draw;
363: /* these are created on the fly if requested */
364: vdraw->draw_max = 5;
365: vdraw->draw_base = 0;
366: vdraw->w = PETSC_DECIDE;
367: vdraw->h = PETSC_DECIDE;
369: PetscCall(PetscCalloc3(vdraw->draw_max, &vdraw->draw, vdraw->draw_max, &vdraw->drawlg, vdraw->draw_max, &vdraw->drawaxis));
370: vdraw->singleton_made = PETSC_FALSE;
371: PetscFunctionReturn(PETSC_SUCCESS);
372: }
374: /*@
375: PetscViewerDrawClear - Clears a `PetscDraw` graphic associated with a `PetscViewer`.
377: Not Collective
379: Input Parameter:
380: . viewer - the `PetscViewer`
382: Level: intermediate
384: .seealso: [](sec_viewers), `PETSCVIEWERDRAW`, `PetscViewerDrawOpen()`, `PetscViewerDrawGetDraw()`,
385: @*/
386: PetscErrorCode PetscViewerDrawClear(PetscViewer viewer)
387: {
388: PetscViewer_Draw *vdraw;
389: PetscBool isdraw;
390: PetscInt i;
392: PetscFunctionBegin;
394: PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERDRAW, &isdraw));
395: if (!isdraw) PetscFunctionReturn(PETSC_SUCCESS);
396: vdraw = (PetscViewer_Draw *)viewer->data;
398: for (i = 0; i < vdraw->draw_max; i++) {
399: if (vdraw->draw[i]) PetscCall(PetscDrawClear(vdraw->draw[i]));
400: }
401: PetscFunctionReturn(PETSC_SUCCESS);
402: }
404: /*@
405: PetscViewerDrawGetPause - Gets the pause value (how long to pause before an image is changed) in the `PETSCVIEWERDRAW` `PetscViewer`
407: Not Collective
409: Input Parameter:
410: . viewer - the `PetscViewer`
412: Output Parameter:
413: . pause - the pause value
415: Level: intermediate
417: .seealso: [](sec_viewers), `PETSCVIEWERDRAW`, `PetscViewerDrawOpen()`, `PetscViewerDrawGetDraw()`,
418: @*/
419: PetscErrorCode PetscViewerDrawGetPause(PetscViewer viewer, PetscReal *pause)
420: {
421: PetscViewer_Draw *vdraw;
422: PetscBool isdraw;
423: PetscInt i;
424: PetscDraw draw;
426: PetscFunctionBegin;
428: PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERDRAW, &isdraw));
429: if (!isdraw) {
430: *pause = 0.0;
431: PetscFunctionReturn(PETSC_SUCCESS);
432: }
433: vdraw = (PetscViewer_Draw *)viewer->data;
435: for (i = 0; i < vdraw->draw_max; i++) {
436: if (vdraw->draw[i]) {
437: PetscCall(PetscDrawGetPause(vdraw->draw[i], pause));
438: PetscFunctionReturn(PETSC_SUCCESS);
439: }
440: }
441: /* none exist yet so create one and get its pause */
442: PetscCall(PetscViewerDrawGetDraw(viewer, 0, &draw));
443: PetscCall(PetscDrawGetPause(draw, pause));
444: PetscFunctionReturn(PETSC_SUCCESS);
445: }
447: /*@
448: PetscViewerDrawSetPause - Sets a pause for each `PetscDraw` in the `PETSCVIEWERDRAW` `PetscViewer`
450: Not Collective
452: Input Parameters:
453: + viewer - the `PetscViewer`
454: - pause - the pause value
456: Level: intermediate
458: .seealso: [](sec_viewers), `PETSCVIEWERDRAW`, `PetscViewerDrawOpen()`, `PetscViewerDrawGetDraw()`,
459: @*/
460: PetscErrorCode PetscViewerDrawSetPause(PetscViewer viewer, PetscReal pause)
461: {
462: PetscViewer_Draw *vdraw;
463: PetscBool isdraw;
464: PetscInt i;
466: PetscFunctionBegin;
468: PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERDRAW, &isdraw));
469: if (!isdraw) PetscFunctionReturn(PETSC_SUCCESS);
470: vdraw = (PetscViewer_Draw *)viewer->data;
472: vdraw->pause = pause;
473: for (i = 0; i < vdraw->draw_max; i++) {
474: if (vdraw->draw[i]) PetscCall(PetscDrawSetPause(vdraw->draw[i], pause));
475: }
476: PetscFunctionReturn(PETSC_SUCCESS);
477: }
479: /*@
480: PetscViewerDrawSetHold - Holds previous image when drawing new image in a `PETSCVIEWERDRAW`
482: Not Collective
484: Input Parameters:
485: + viewer - the `PetscViewer`
486: - hold - `PETSC_TRUE` indicates to hold the previous image
488: Level: intermediate
490: .seealso: [](sec_viewers), `PETSCVIEWERDRAW`, `PetscViewerDrawOpen()`, `PetscViewerDrawGetDraw()`,
491: @*/
492: PetscErrorCode PetscViewerDrawSetHold(PetscViewer viewer, PetscBool hold)
493: {
494: PetscViewer_Draw *vdraw;
495: PetscBool isdraw;
497: PetscFunctionBegin;
499: PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERDRAW, &isdraw));
500: if (!isdraw) PetscFunctionReturn(PETSC_SUCCESS);
501: vdraw = (PetscViewer_Draw *)viewer->data;
503: vdraw->hold = hold;
504: PetscFunctionReturn(PETSC_SUCCESS);
505: }
507: /*@
508: PetscViewerDrawGetHold - Checks if the `PETSCVIEWERDRAW` `PetscViewer` holds previous image when drawing new image
510: Not Collective
512: Input Parameter:
513: . viewer - the `PetscViewer`
515: Output Parameter:
516: . hold - indicates to hold or not
518: Level: intermediate
520: .seealso: [](sec_viewers), `PETSCVIEWERDRAW`, `PetscViewerDrawOpen()`, `PetscViewerDrawGetDraw()`,
521: @*/
522: PetscErrorCode PetscViewerDrawGetHold(PetscViewer viewer, PetscBool *hold)
523: {
524: PetscViewer_Draw *vdraw;
525: PetscBool isdraw;
527: PetscFunctionBegin;
529: PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERDRAW, &isdraw));
530: if (!isdraw) {
531: *hold = PETSC_FALSE;
532: PetscFunctionReturn(PETSC_SUCCESS);
533: }
534: vdraw = (PetscViewer_Draw *)viewer->data;
536: *hold = vdraw->hold;
537: PetscFunctionReturn(PETSC_SUCCESS);
538: }
540: /*
541: The variable Petsc_Viewer_Draw_keyval is used to indicate an MPI attribute that
542: is attached to a communicator, in this case the attribute is a PetscViewer.
543: */
544: PetscMPIInt Petsc_Viewer_Draw_keyval = MPI_KEYVAL_INVALID;
546: /*@C
547: PETSC_VIEWER_DRAW_ - Creates a window `PETSCVIEWERDRAW` `PetscViewer` shared by all processors
548: in an MPI communicator.
550: Collective
552: Input Parameter:
553: . comm - the MPI communicator to share the window `PetscViewer`
555: Level: intermediate
557: Notes:
558: This object is destroyed in `PetscFinalize()`, `PetscViewerDestroy()` should never be called on it
560: Unlike almost all other PETSc routines, `PETSC_VIEWER_DRAW_()` does not return
561: an error code. The window is usually used in the form
562: .vb
563: XXXView(XXX object, PETSC_VIEWER_DRAW_(comm));
564: .ve
566: .seealso: [](sec_viewers), `PETSCVIEWERDRAW`, `PetscViewer`, `PETSC_VIEWER_DRAW_WORLD`, `PETSC_VIEWER_DRAW_SELF`, `PetscViewerDrawOpen()`,
567: @*/
568: PetscViewer PETSC_VIEWER_DRAW_(MPI_Comm comm)
569: {
570: PetscMPIInt flag;
571: PetscViewer viewer;
572: MPI_Comm ncomm;
574: PetscFunctionBegin;
575: PetscCallNull(PetscCommDuplicate(comm, &ncomm, NULL));
576: if (Petsc_Viewer_Draw_keyval == MPI_KEYVAL_INVALID) { PetscCallMPINull(MPI_Comm_create_keyval(MPI_COMM_NULL_COPY_FN, MPI_COMM_NULL_DELETE_FN, &Petsc_Viewer_Draw_keyval, NULL)); }
577: PetscCallMPINull(MPI_Comm_get_attr(ncomm, Petsc_Viewer_Draw_keyval, (void **)&viewer, &flag));
578: if (!flag) { /* PetscViewer not yet created */
579: PetscCallNull(PetscViewerDrawOpen(ncomm, NULL, NULL, PETSC_DECIDE, PETSC_DECIDE, 300, 300, &viewer));
580: PetscCallNull(PetscObjectRegisterDestroy((PetscObject)viewer));
581: PetscCallMPINull(MPI_Comm_set_attr(ncomm, Petsc_Viewer_Draw_keyval, (void *)viewer));
582: }
583: PetscCallNull(PetscCommDestroy(&ncomm));
584: PetscFunctionReturn(viewer);
585: }
587: /*@
588: PetscViewerDrawSetBounds - sets the upper and lower bounds to be used in plotting in a `PETSCVIEWERDRAW` `PetscViewer`
590: Collective
592: Input Parameters:
593: + viewer - the Petsc`Viewer` (created with `PetscViewerDrawOpen()`)
594: . nbounds - number of plots that can be made with this viewer, for example the dof passed to `DMDACreate()`
595: - 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, .....
597: Options Database Key:
598: . -draw_bounds minF0,maxF0,minF1,maxF1 - the lower left and upper right bounds
600: Level: intermediate
602: Note:
603: 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
604: 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
605: this viewer. Otherwise the color to physical value meaning changes with each new image if this is not set.
607: .seealso: [](sec_viewers), `PETSCVIEWERDRAW`, `PetscViewerDrawGetLG()`, `PetscViewerDrawGetAxis()`, `PetscViewerDrawOpen()`
608: @*/
609: PetscErrorCode PetscViewerDrawSetBounds(PetscViewer viewer, PetscInt nbounds, const PetscReal *bounds)
610: {
611: PetscViewer_Draw *vdraw;
612: PetscBool isdraw;
614: PetscFunctionBegin;
616: PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERDRAW, &isdraw));
617: if (!isdraw) PetscFunctionReturn(PETSC_SUCCESS);
618: vdraw = (PetscViewer_Draw *)viewer->data;
620: vdraw->nbounds = nbounds;
621: PetscCall(PetscFree(vdraw->bounds));
622: PetscCall(PetscMalloc1(2 * nbounds, &vdraw->bounds));
623: PetscCall(PetscArraycpy(vdraw->bounds, bounds, 2 * nbounds));
624: PetscFunctionReturn(PETSC_SUCCESS);
625: }
627: /*@C
628: PetscViewerDrawGetBounds - gets the upper and lower bounds to be used in plotting set with `PetscViewerDrawSetBounds()`
630: Collective
632: Input Parameter:
633: . viewer - the `PetscViewer` (created with `PetscViewerDrawOpen()`)
635: Output Parameters:
636: + nbounds - number of plots that can be made with this viewer, for example the dof passed to `DMDACreate()`
637: - 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, .....
639: Level: intermediate
641: .seealso: [](sec_viewers), `PETSCVIEWERDRAW`, `PetscViewerDrawGetLG()`, `PetscViewerDrawGetAxis()`, `PetscViewerDrawOpen()`, `PetscViewerDrawSetBounds()`
642: @*/
643: PetscErrorCode PetscViewerDrawGetBounds(PetscViewer viewer, PetscInt *nbounds, const PetscReal *bounds[])
644: {
645: PetscViewer_Draw *vdraw;
646: PetscBool isdraw;
648: PetscFunctionBegin;
650: PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERDRAW, &isdraw));
651: if (!isdraw) {
652: if (nbounds) *nbounds = 0;
653: if (bounds) *bounds = NULL;
654: PetscFunctionReturn(PETSC_SUCCESS);
655: }
656: vdraw = (PetscViewer_Draw *)viewer->data;
658: if (nbounds) *nbounds = vdraw->nbounds;
659: if (bounds) *bounds = vdraw->bounds;
660: PetscFunctionReturn(PETSC_SUCCESS);
661: }
663: /*@C
664: PetscViewerMonitorLGSetUp - sets up a viewer to be used by line graph monitoring routines such as `KSPMonitorResidualDrawLG()`
666: Collective
668: Input Parameters:
669: + viewer - the viewer in which to display the line graphs, it not a `PETSCVIEWERDRAW` it will set to that `PetscViewerType`
670: . host - the host to open the window on, 'NULL' indicates the local host
671: . title - the title at the top of the window
672: . metric - the label above the graph
673: . l - the number of curves
674: . names - the names of each curve to be used in displaying the legend. May be 'NULL'
675: . x - horizontal screen coordinate of the upper left corner of window, or use `PETSC_DECIDE`
676: . y - vertical screen coordinate of the upper left corner of window, or use `PETSC_DECIDE`
677: . m - 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`
678: - n - 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`
680: Level: developer
682: .seealso: `PetscViewer()`, `PETSCVIEWERDRAW`, `PetscViewerDrawGetDrawLG()`, `PetscViewerDrawOpen()`, `PetscViewerDrawSetInfo()`
683: @*/
684: PetscErrorCode PetscViewerMonitorLGSetUp(PetscViewer viewer, const char host[], const char title[], const char metric[], PetscInt l, const char *names[], int x, int y, int m, int n) PeNS
685: {
686: PetscDrawAxis axis;
687: PetscDrawLG lg;
689: PetscFunctionBegin;
690: PetscCall(PetscViewerSetType(viewer, PETSCVIEWERDRAW));
691: PetscCall(PetscViewerDrawSetInfo(viewer, host, title, x, y, m, n));
692: PetscCall(PetscViewerDrawGetDrawLG(viewer, 0, &lg));
693: if (names) PetscCall(PetscDrawLGSetLegend(lg, names));
694: PetscCall(PetscDrawLGSetFromOptions(lg));
695: PetscCall(PetscDrawLGGetAxis(lg, &axis));
696: PetscCall(PetscDrawAxisSetLabels(axis, "Convergence", "Iteration", metric));
697: PetscFunctionReturn(PETSC_SUCCESS);
698: }