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: PetscViewer_Draw *vdraw = (PetscViewer_Draw *)v->data;
29: PetscFunctionBegin;
30: for (PetscInt i = 0; i < vdraw->draw_max; i++) {
31: if (vdraw->draw[i]) PetscCall(PetscDrawFlush(vdraw->draw[i]));
32: }
33: PetscFunctionReturn(PETSC_SUCCESS);
34: }
36: /*@
37: PetscViewerDrawBaseAdd - add to the base integer that is added to the `windownumber` passed to `PetscViewerDrawGetDraw()`
39: Logically Collective
41: Input Parameters:
42: + viewer - the `PetscViewer` (created with `PetscViewerDrawOpen()`)
43: - windownumber - how much to add to the base
45: Level: developer
47: Note:
48: A `PETSCVIEWERDRAW` may have multiple `PetscDraw` subwindows, this increases the number of the subwindow that is returned with `PetscViewerDrawGetDraw()`
50: .seealso: [](sec_viewers), `PetscViewerDrawGetLG()`, `PetscViewerDrawGetAxis()`, `PetscViewerDrawOpen()`, `PetscViewerDrawGetDraw()`, `PetscViewerDrawBaseSet()`
51: @*/
52: PetscErrorCode PetscViewerDrawBaseAdd(PetscViewer viewer, PetscInt windownumber)
53: {
54: PetscViewer_Draw *vdraw;
55: PetscBool isdraw;
57: PetscFunctionBegin;
60: PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERDRAW, &isdraw));
61: PetscCheck(isdraw, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Must be draw type PetscViewer");
62: vdraw = (PetscViewer_Draw *)viewer->data;
64: PetscCheck(windownumber + vdraw->draw_base >= 0, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Resulting base %" PetscInt_FMT " cannot be negative", windownumber + vdraw->draw_base);
65: vdraw->draw_base += windownumber;
66: PetscFunctionReturn(PETSC_SUCCESS);
67: }
69: /*@
70: PetscViewerDrawBaseSet - sets the base integer that is added to the `windownumber` passed to `PetscViewerDrawGetDraw()`
72: Logically Collective
74: Input Parameters:
75: + viewer - the `PetscViewer` (created with `PetscViewerDrawOpen()`)
76: - windownumber - value to set the base
78: Level: developer
80: Note:
81: A `PETSCVIEWERDRAW` may have multiple `PetscDraw` subwindows, this increases the number of the subwindow that is returned with `PetscViewerDrawGetDraw()`
83: .seealso: [](sec_viewers), `PetscViewerDrawGetLG()`, `PetscViewerDrawGetAxis()`, `PetscViewerDrawOpen()`, `PetscViewerDrawGetDraw()`, `PetscViewerDrawBaseAdd()`
84: @*/
85: PetscErrorCode PetscViewerDrawBaseSet(PetscViewer viewer, PetscInt windownumber)
86: {
87: PetscViewer_Draw *vdraw;
88: PetscBool isdraw;
90: PetscFunctionBegin;
93: PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERDRAW, &isdraw));
94: PetscCheck(isdraw, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Must be draw type PetscViewer");
95: vdraw = (PetscViewer_Draw *)viewer->data;
97: PetscCheck(windownumber >= 0, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Resulting base %" PetscInt_FMT " cannot be negative", windownumber);
98: vdraw->draw_base = windownumber;
99: PetscFunctionReturn(PETSC_SUCCESS);
100: }
102: PetscErrorCode PetscViewerDrawResize(PetscViewer v, int w, int h)
103: {
104: PetscViewer_Draw *vdraw;
105: PetscBool isdraw;
107: PetscFunctionBegin;
109: PetscCall(PetscObjectTypeCompare((PetscObject)v, PETSCVIEWERDRAW, &isdraw));
110: if (!isdraw) PetscFunctionReturn(PETSC_SUCCESS);
111: vdraw = (PetscViewer_Draw *)v->data;
113: if (w >= 1) vdraw->w = w;
114: if (h >= 1) vdraw->h = h;
115: PetscFunctionReturn(PETSC_SUCCESS);
116: }
118: PetscErrorCode PetscViewerDrawSetInfo(PetscViewer v, const char display[], const char title[], int x, int y, int w, int h)
119: {
120: PetscViewer_Draw *vdraw;
121: PetscBool isdraw;
123: PetscFunctionBegin;
125: PetscCall(PetscObjectTypeCompare((PetscObject)v, PETSCVIEWERDRAW, &isdraw));
126: if (!isdraw) PetscFunctionReturn(PETSC_SUCCESS);
127: vdraw = (PetscViewer_Draw *)v->data;
129: PetscCall(PetscStrallocpy(display, &vdraw->display));
130: PetscCall(PetscStrallocpy(title, &vdraw->title));
131: if (w >= 1) vdraw->w = w;
132: if (h >= 1) vdraw->h = h;
133: PetscFunctionReturn(PETSC_SUCCESS);
134: }
136: PetscErrorCode PetscViewerDrawSetTitle(PetscViewer v, const char title[])
137: {
138: PetscViewer_Draw *vdraw;
139: PetscBool isdraw;
141: PetscFunctionBegin;
143: PetscCall(PetscObjectTypeCompare((PetscObject)v, PETSCVIEWERDRAW, &isdraw));
144: if (!isdraw) PetscFunctionReturn(PETSC_SUCCESS);
145: vdraw = (PetscViewer_Draw *)v->data;
147: PetscCall(PetscFree(vdraw->title));
148: PetscCall(PetscStrallocpy(title, &vdraw->title));
149: PetscFunctionReturn(PETSC_SUCCESS);
150: }
152: PetscErrorCode PetscViewerDrawGetTitle(PetscViewer v, const char *title[])
153: {
154: PetscViewer_Draw *vdraw;
155: PetscBool isdraw;
157: PetscFunctionBegin;
159: PetscCall(PetscObjectTypeCompare((PetscObject)v, PETSCVIEWERDRAW, &isdraw));
160: PetscCheck(isdraw, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Must be draw type PetscViewer");
161: vdraw = (PetscViewer_Draw *)v->data;
163: *title = vdraw->title;
164: PetscFunctionReturn(PETSC_SUCCESS);
165: }
167: /*@
168: PetscViewerDrawOpen - Opens a `PetscDraw` window for use as a `PetscViewer` with type
169: `PETSCVIEWERDRAW`.
171: Collective
173: Input Parameters:
174: + comm - communicator that will share window
175: . display - the X display on which to open, or `NULL` for the local machine
176: . title - the title to put in the title bar, or `NULL` for no title
177: . x - horizontal screen coordinate of the upper left corner of window, or use `PETSC_DECIDE`
178: . y - vertical screen coordinate of the upper left corner of window, or use `PETSC_DECIDE`
179: . 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`
180: - 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`
182: Output Parameter:
183: . viewer - the `PetscViewer`
185: Options Database Keys:
186: + -draw_type - use x or null
187: . -nox - Disables all x-windows output
188: . -display name - Specifies name of machine for the X display
189: . -geometry x,y,w,h - allows setting the window location and size
190: - -draw_pause pause - Sets time (in seconds) that the
191: program pauses after `PetscDrawPause()` has been called
192: (0 is default, -1 implies until user input).
194: Level: beginner
196: Notes:
197: If you want to do graphics in this window, you must call `PetscViewerDrawGetDraw()` and
198: perform the graphics on the `PetscDraw` object.
200: Format options include\:
201: + `PETSC_VIEWER_DRAW_BASIC` - displays with basic format
202: - `PETSC_VIEWER_DRAW_LG` - displays using a line graph
204: Fortran Note:
205: Whenever indicating null character data in a Fortran code,
206: `PETSC_NULL_CHARACTER` must be employed. Thus, `PETSC_NULL_CHARACTER` can be
207: used for the `display` and `title` input parameters.
209: .seealso: [](sec_viewers), `PETSCVIEWERDRAW`, `PetscDrawCreate()`, `PetscViewerDestroy()`, `PetscViewerDrawGetDraw()`, `PetscViewerCreate()`, `PETSC_VIEWER_DRAW_`,
210: `PETSC_VIEWER_DRAW_WORLD`, `PETSC_VIEWER_DRAW_SELF`
211: @*/
212: PetscErrorCode PetscViewerDrawOpen(MPI_Comm comm, const char display[], const char title[], int x, int y, int w, int h, PetscViewer *viewer)
213: {
214: PetscFunctionBegin;
215: PetscCall(PetscViewerCreate(comm, viewer));
216: PetscCall(PetscViewerSetType(*viewer, PETSCVIEWERDRAW));
217: PetscCall(PetscViewerDrawSetInfo(*viewer, display, title, x, y, w, h));
218: PetscFunctionReturn(PETSC_SUCCESS);
219: }
221: #include <petsc/private/drawimpl.h>
223: static PetscErrorCode PetscViewerGetSubViewer_Draw(PetscViewer viewer, MPI_Comm comm, PetscViewer *sviewer)
224: {
225: PetscMPIInt rank;
226: PetscInt i;
227: PetscViewer_Draw *vdraw = (PetscViewer_Draw *)viewer->data, *svdraw;
229: PetscFunctionBegin;
230: PetscCheck(!vdraw->singleton_made, PETSC_COMM_SELF, PETSC_ERR_ORDER, "Trying to get SubViewer without first restoring previous");
231: /* only processor zero can use the PetscViewer draw singleton */
232: PetscCallMPI(MPI_Comm_rank(PetscObjectComm((PetscObject)viewer), &rank));
233: if (rank == 0) {
234: PetscMPIInt flg;
235: PetscDraw draw, sdraw;
237: PetscCallMPI(MPI_Comm_compare(PETSC_COMM_SELF, comm, &flg));
238: PetscCheck(flg == MPI_IDENT || flg == MPI_CONGRUENT, PETSC_COMM_SELF, PETSC_ERR_SUP, "PetscViewerGetSubViewer() for PETSCVIEWERDRAW requires a singleton MPI_Comm");
239: PetscCall(PetscViewerCreate(comm, sviewer));
240: PetscCall(PetscViewerSetType(*sviewer, PETSCVIEWERDRAW));
241: svdraw = (PetscViewer_Draw *)(*sviewer)->data;
242: (*sviewer)->format = viewer->format;
243: for (i = 0; i < vdraw->draw_max; i++) { /* XXX this is wrong if svdraw->draw_max (initially 5) < vdraw->draw_max */
244: if (vdraw->draw[i]) PetscCall(PetscDrawGetSingleton(vdraw->draw[i], &svdraw->draw[i]));
245: }
246: PetscCall(PetscViewerDrawGetDraw(viewer, 0, &draw));
247: PetscCall(PetscViewerDrawGetDraw(*sviewer, 0, &sdraw));
248: if (draw->savefilename) {
249: PetscCall(PetscDrawSetSave(sdraw, draw->savefilename));
250: sdraw->savefilecount = draw->savefilecount;
251: sdraw->savesinglefile = draw->savesinglefile;
252: sdraw->savemoviefps = draw->savemoviefps;
253: sdraw->saveonclear = draw->saveonclear;
254: sdraw->saveonflush = draw->saveonflush;
255: }
256: if (draw->savefinalfilename) PetscCall(PetscDrawSetSaveFinalImage(sdraw, draw->savefinalfilename));
257: } else {
258: PetscDraw draw;
259: PetscCall(PetscViewerDrawGetDraw(viewer, 0, &draw));
260: }
261: vdraw->singleton_made = PETSC_TRUE;
262: PetscFunctionReturn(PETSC_SUCCESS);
263: }
265: static PetscErrorCode PetscViewerRestoreSubViewer_Draw(PetscViewer viewer, MPI_Comm comm, PetscViewer *sviewer)
266: {
267: PetscMPIInt rank;
268: PetscInt i;
269: PetscViewer_Draw *vdraw = (PetscViewer_Draw *)viewer->data, *svdraw;
271: PetscFunctionBegin;
272: PetscCheck(vdraw->singleton_made, PETSC_COMM_SELF, PETSC_ERR_ORDER, "Trying to restore a singleton that was not gotten");
273: PetscCallMPI(MPI_Comm_rank(PetscObjectComm((PetscObject)viewer), &rank));
274: if (rank == 0) {
275: PetscDraw draw, sdraw;
277: PetscCall(PetscViewerDrawGetDraw(viewer, 0, &draw));
278: PetscCall(PetscViewerDrawGetDraw(*sviewer, 0, &sdraw));
279: if (draw->savefilename) {
280: draw->savefilecount = sdraw->savefilecount;
281: PetscCallMPI(MPI_Bcast(&draw->savefilecount, 1, MPIU_INT, 0, PetscObjectComm((PetscObject)draw)));
282: }
283: svdraw = (PetscViewer_Draw *)(*sviewer)->data;
284: for (i = 0; i < vdraw->draw_max; i++) {
285: if (vdraw->draw[i] && svdraw->draw[i]) PetscCall(PetscDrawRestoreSingleton(vdraw->draw[i], &svdraw->draw[i]));
286: }
287: PetscCall(PetscFree3(svdraw->draw, svdraw->drawlg, svdraw->drawaxis));
288: PetscCall(PetscFree((*sviewer)->data));
289: PetscCall(PetscHeaderDestroy(sviewer));
290: } else {
291: PetscDraw draw;
293: PetscCall(PetscViewerDrawGetDraw(viewer, 0, &draw));
294: if (draw->savefilename) PetscCallMPI(MPI_Bcast(&draw->savefilecount, 1, MPIU_INT, 0, PetscObjectComm((PetscObject)draw)));
295: }
297: vdraw->singleton_made = PETSC_FALSE;
298: PetscFunctionReturn(PETSC_SUCCESS);
299: }
301: static PetscErrorCode PetscViewerSetFromOptions_Draw(PetscViewer v, PetscOptionItems PetscOptionsObject)
302: {
303: PetscReal bounds[16];
304: PetscInt nbounds = 16;
305: PetscBool flg;
307: PetscFunctionBegin;
308: PetscOptionsHeadBegin(PetscOptionsObject, "Draw PetscViewer Options");
309: PetscCall(PetscOptionsRealArray("-draw_bounds", "Bounds to put on plots axis", "PetscViewerDrawSetBounds", bounds, &nbounds, &flg));
310: if (flg) PetscCall(PetscViewerDrawSetBounds(v, nbounds / 2, bounds));
311: PetscOptionsHeadEnd();
312: PetscFunctionReturn(PETSC_SUCCESS);
313: }
315: static PetscErrorCode PetscViewerView_Draw(PetscViewer viewer, PetscViewer v)
316: {
317: PetscDraw draw;
318: PetscInt i;
319: PetscViewer_Draw *vdraw = (PetscViewer_Draw *)viewer->data;
320: PetscBool isascii;
322: PetscFunctionBegin;
323: PetscCall(PetscObjectTypeCompare((PetscObject)v, PETSCVIEWERASCII, &isascii));
324: if (isascii) PetscCall(PetscViewerASCIIPrintf(v, "Draw viewer is of type %s\n", vdraw->drawtype));
325: /* If the PetscViewer has just been created then no vdraw->draw yet
326: exists so this will not actually call the viewer on any draws. */
327: for (i = 0; i < vdraw->draw_base; i++) {
328: if (vdraw->draw[i]) {
329: PetscCall(PetscViewerDrawGetDraw(viewer, i, &draw));
330: PetscCall(PetscDrawView(draw, v));
331: }
332: }
333: PetscFunctionReturn(PETSC_SUCCESS);
334: }
336: /*MC
337: PETSCVIEWERDRAW - A viewer that generates graphics, either to the screen or a file
339: Level: beginner
341: .seealso: [](sec_viewers), `PetscViewerDrawOpen()`, `PetscViewerDrawGetDraw()`, `PETSC_VIEWER_DRAW_()`, `PETSC_VIEWER_DRAW_SELF`, `PETSC_VIEWER_DRAW_WORLD`,
342: `PetscViewerCreate()`, `PetscViewerASCIIOpen()`, `PetscViewerBinaryOpen()`, `PETSCVIEWERBINARY`,
343: `PetscViewerMatlabOpen()`, `VecView()`, `DMView()`, `PetscViewerMatlabPutArray()`, `PETSCVIEWERASCII`, `PETSCVIEWERMATLAB`,
344: `PetscViewerFileSetName()`, `PetscViewerFileSetMode()`, `PetscViewerFormat`, `PetscViewerType`, `PetscViewerSetType()`
345: M*/
346: PETSC_EXTERN PetscErrorCode PetscViewerCreate_Draw(PetscViewer viewer)
347: {
348: PetscViewer_Draw *vdraw;
350: PetscFunctionBegin;
351: PetscCall(PetscNew(&vdraw));
352: viewer->data = (void *)vdraw;
354: viewer->ops->flush = PetscViewerFlush_Draw;
355: viewer->ops->view = PetscViewerView_Draw;
356: viewer->ops->destroy = PetscViewerDestroy_Draw;
357: viewer->ops->setfromoptions = PetscViewerSetFromOptions_Draw;
358: viewer->ops->getsubviewer = PetscViewerGetSubViewer_Draw;
359: viewer->ops->restoresubviewer = PetscViewerRestoreSubViewer_Draw;
361: /* these are created on the fly if requested */
362: vdraw->draw_max = 5;
363: vdraw->draw_base = 0;
364: vdraw->w = PETSC_DECIDE;
365: vdraw->h = PETSC_DECIDE;
367: PetscCall(PetscCalloc3(vdraw->draw_max, &vdraw->draw, vdraw->draw_max, &vdraw->drawlg, vdraw->draw_max, &vdraw->drawaxis));
368: vdraw->singleton_made = PETSC_FALSE;
369: PetscFunctionReturn(PETSC_SUCCESS);
370: }
372: /*@
373: PetscViewerDrawClear - Clears a `PetscDraw` graphic associated with a `PetscViewer`.
375: Not Collective
377: Input Parameter:
378: . viewer - the `PetscViewer`
380: Level: intermediate
382: .seealso: [](sec_viewers), `PETSCVIEWERDRAW`, `PetscViewerDrawOpen()`, `PetscViewerDrawGetDraw()`
383: @*/
384: PetscErrorCode PetscViewerDrawClear(PetscViewer viewer)
385: {
386: PetscViewer_Draw *vdraw;
387: PetscBool isdraw;
389: PetscFunctionBegin;
391: PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERDRAW, &isdraw));
392: if (!isdraw) PetscFunctionReturn(PETSC_SUCCESS);
393: vdraw = (PetscViewer_Draw *)viewer->data;
395: for (PetscInt i = 0; i < vdraw->draw_max; i++) {
396: if (vdraw->draw[i]) PetscCall(PetscDrawClear(vdraw->draw[i]));
397: }
398: PetscFunctionReturn(PETSC_SUCCESS);
399: }
401: /*@
402: PetscViewerDrawGetPause - Gets the pause value (how long to pause before an image is changed) in the `PETSCVIEWERDRAW` `PetscViewer`
404: Not Collective
406: Input Parameter:
407: . viewer - the `PetscViewer`
409: Output Parameter:
410: . pause - the pause value
412: Level: intermediate
414: .seealso: [](sec_viewers), `PETSCVIEWERDRAW`, `PetscViewerDrawOpen()`, `PetscViewerDrawGetDraw()`
415: @*/
416: PetscErrorCode PetscViewerDrawGetPause(PetscViewer viewer, PetscReal *pause)
417: {
418: PetscViewer_Draw *vdraw;
419: PetscBool isdraw;
420: PetscDraw draw;
422: PetscFunctionBegin;
424: PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERDRAW, &isdraw));
425: if (!isdraw) {
426: *pause = 0.0;
427: PetscFunctionReturn(PETSC_SUCCESS);
428: }
429: vdraw = (PetscViewer_Draw *)viewer->data;
431: for (PetscInt i = 0; i < vdraw->draw_max; i++) {
432: if (vdraw->draw[i]) {
433: PetscCall(PetscDrawGetPause(vdraw->draw[i], pause));
434: PetscFunctionReturn(PETSC_SUCCESS);
435: }
436: }
437: /* none exist yet so create one and get its pause */
438: PetscCall(PetscViewerDrawGetDraw(viewer, 0, &draw));
439: PetscCall(PetscDrawGetPause(draw, pause));
440: PetscFunctionReturn(PETSC_SUCCESS);
441: }
443: /*@
444: PetscViewerDrawSetPause - Sets a pause for each `PetscDraw` in the `PETSCVIEWERDRAW` `PetscViewer`
446: Not Collective
448: Input Parameters:
449: + viewer - the `PetscViewer`
450: - pause - the pause value
452: Level: intermediate
454: .seealso: [](sec_viewers), `PETSCVIEWERDRAW`, `PetscViewerDrawOpen()`, `PetscViewerDrawGetDraw()`
455: @*/
456: PetscErrorCode PetscViewerDrawSetPause(PetscViewer viewer, PetscReal pause)
457: {
458: PetscViewer_Draw *vdraw;
459: PetscBool isdraw;
461: PetscFunctionBegin;
463: PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERDRAW, &isdraw));
464: if (!isdraw) PetscFunctionReturn(PETSC_SUCCESS);
465: vdraw = (PetscViewer_Draw *)viewer->data;
467: vdraw->pause = pause;
468: for (PetscInt i = 0; i < vdraw->draw_max; i++) {
469: if (vdraw->draw[i]) PetscCall(PetscDrawSetPause(vdraw->draw[i], pause));
470: }
471: PetscFunctionReturn(PETSC_SUCCESS);
472: }
474: /*@
475: PetscViewerDrawSetHold - Holds previous image when drawing new image in a `PETSCVIEWERDRAW`
477: Not Collective
479: Input Parameters:
480: + viewer - the `PetscViewer`
481: - hold - `PETSC_TRUE` indicates to hold the previous image
483: Level: intermediate
485: .seealso: [](sec_viewers), `PETSCVIEWERDRAW`, `PetscViewerDrawOpen()`, `PetscViewerDrawGetDraw()`
486: @*/
487: PetscErrorCode PetscViewerDrawSetHold(PetscViewer viewer, PetscBool hold)
488: {
489: PetscViewer_Draw *vdraw;
490: PetscBool isdraw;
492: PetscFunctionBegin;
494: PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERDRAW, &isdraw));
495: if (!isdraw) PetscFunctionReturn(PETSC_SUCCESS);
496: vdraw = (PetscViewer_Draw *)viewer->data;
498: vdraw->hold = hold;
499: PetscFunctionReturn(PETSC_SUCCESS);
500: }
502: /*@
503: PetscViewerDrawGetHold - Checks if the `PETSCVIEWERDRAW` `PetscViewer` holds previous image when drawing new image
505: Not Collective
507: Input Parameter:
508: . viewer - the `PetscViewer`
510: Output Parameter:
511: . hold - indicates to hold or not
513: Level: intermediate
515: .seealso: [](sec_viewers), `PETSCVIEWERDRAW`, `PetscViewerDrawOpen()`, `PetscViewerDrawGetDraw()`
516: @*/
517: PetscErrorCode PetscViewerDrawGetHold(PetscViewer viewer, PetscBool *hold)
518: {
519: PetscViewer_Draw *vdraw;
520: PetscBool isdraw;
522: PetscFunctionBegin;
524: PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERDRAW, &isdraw));
525: if (!isdraw) {
526: *hold = PETSC_FALSE;
527: PetscFunctionReturn(PETSC_SUCCESS);
528: }
529: vdraw = (PetscViewer_Draw *)viewer->data;
531: *hold = vdraw->hold;
532: PetscFunctionReturn(PETSC_SUCCESS);
533: }
535: /*
536: The variable Petsc_Viewer_Draw_keyval is used to indicate an MPI attribute that
537: is attached to a communicator, in this case the attribute is a PetscViewer.
538: */
539: PetscMPIInt Petsc_Viewer_Draw_keyval = MPI_KEYVAL_INVALID;
541: /*@C
542: PETSC_VIEWER_DRAW_ - Creates a window `PETSCVIEWERDRAW` `PetscViewer` shared by all processors
543: in an MPI communicator.
545: Collective
547: Input Parameter:
548: . comm - the MPI communicator to share the window `PetscViewer`
550: Level: intermediate
552: Notes:
553: This object is destroyed in `PetscFinalize()`, `PetscViewerDestroy()` should never be called on it
555: Unlike almost all other PETSc routines, `PETSC_VIEWER_DRAW_()` does not return
556: an error code. The window is usually used in the form
557: .vb
558: XXXView(XXX object, PETSC_VIEWER_DRAW_(comm));
559: .ve
561: .seealso: [](sec_viewers), `PETSCVIEWERDRAW`, `PetscViewer`, `PETSC_VIEWER_DRAW_WORLD`, `PETSC_VIEWER_DRAW_SELF`, `PetscViewerDrawOpen()`,
562: @*/
563: PetscViewer PETSC_VIEWER_DRAW_(MPI_Comm comm)
564: {
565: PetscMPIInt iflg;
566: PetscViewer viewer;
567: MPI_Comm ncomm;
569: PetscFunctionBegin;
570: PetscCallNull(PetscCommDuplicate(comm, &ncomm, NULL));
571: 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));
572: PetscCallMPINull(MPI_Comm_get_attr(ncomm, Petsc_Viewer_Draw_keyval, (void **)&viewer, &iflg));
573: if (!iflg) { /* PetscViewer not yet created */
574: PetscCallNull(PetscViewerDrawOpen(ncomm, NULL, NULL, PETSC_DECIDE, PETSC_DECIDE, 300, 300, &viewer));
575: PetscCallNull(PetscObjectRegisterDestroy((PetscObject)viewer));
576: PetscCallMPINull(MPI_Comm_set_attr(ncomm, Petsc_Viewer_Draw_keyval, (void *)viewer));
577: }
578: PetscCallNull(PetscCommDestroy(&ncomm));
579: PetscFunctionReturn(viewer);
580: }
582: /*@
583: PetscViewerDrawSetBounds - sets the upper and lower bounds to be used in plotting in a `PETSCVIEWERDRAW` `PetscViewer`
585: Collective
587: Input Parameters:
588: + viewer - the `PetscViewer` (created with `PetscViewerDrawOpen()`)
589: . nbounds - number of plots that can be made with this viewer, for example the dof passed to `DMDACreate()`
590: - 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, .....
592: Options Database Key:
593: . -draw_bounds minF0,maxF0,minF1,maxF1 - the lower left and upper right bounds
595: Level: intermediate
597: Note:
598: 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
599: 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
600: this viewer. Otherwise the color to physical value meaning changes with each new image if this is not set.
602: .seealso: [](sec_viewers), `PETSCVIEWERDRAW`, `PetscViewerDrawGetLG()`, `PetscViewerDrawGetAxis()`, `PetscViewerDrawOpen()`
603: @*/
604: PetscErrorCode PetscViewerDrawSetBounds(PetscViewer viewer, PetscInt nbounds, const PetscReal *bounds)
605: {
606: PetscViewer_Draw *vdraw;
607: PetscBool isdraw;
609: PetscFunctionBegin;
611: PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERDRAW, &isdraw));
612: if (!isdraw) PetscFunctionReturn(PETSC_SUCCESS);
613: vdraw = (PetscViewer_Draw *)viewer->data;
615: vdraw->nbounds = nbounds;
616: PetscCall(PetscFree(vdraw->bounds));
617: PetscCall(PetscMalloc1(2 * nbounds, &vdraw->bounds));
618: PetscCall(PetscArraycpy(vdraw->bounds, bounds, 2 * nbounds));
619: PetscFunctionReturn(PETSC_SUCCESS);
620: }
622: /*@C
623: PetscViewerDrawGetBounds - gets the upper and lower bounds to be used in plotting set with `PetscViewerDrawSetBounds()`
625: Collective
627: Input Parameter:
628: . viewer - the `PetscViewer` (created with `PetscViewerDrawOpen()`)
630: Output Parameters:
631: + nbounds - number of plots that can be made with this viewer, for example the dof passed to `DMDACreate()`
632: - 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, .....
634: Level: intermediate
636: .seealso: [](sec_viewers), `PETSCVIEWERDRAW`, `PetscViewerDrawGetLG()`, `PetscViewerDrawGetAxis()`, `PetscViewerDrawOpen()`, `PetscViewerDrawSetBounds()`
637: @*/
638: PetscErrorCode PetscViewerDrawGetBounds(PetscViewer viewer, PetscInt *nbounds, const PetscReal *bounds[])
639: {
640: PetscViewer_Draw *vdraw;
641: PetscBool isdraw;
643: PetscFunctionBegin;
645: PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERDRAW, &isdraw));
646: if (!isdraw) {
647: if (nbounds) *nbounds = 0;
648: if (bounds) *bounds = NULL;
649: PetscFunctionReturn(PETSC_SUCCESS);
650: }
651: vdraw = (PetscViewer_Draw *)viewer->data;
653: if (nbounds) *nbounds = vdraw->nbounds;
654: if (bounds) *bounds = vdraw->bounds;
655: PetscFunctionReturn(PETSC_SUCCESS);
656: }
658: /*@C
659: PetscViewerMonitorLGSetUp - sets up a viewer to be used by line graph monitoring routines such as `KSPMonitorResidualDrawLG()`
661: Collective
663: Input Parameters:
664: + viewer - the viewer in which to display the line graphs, it not a `PETSCVIEWERDRAW` it will set to that `PetscViewerType`
665: . host - the host to open the window on, 'NULL' indicates the local host
666: . title - the title at the top of the window
667: . metric - the label above the graph
668: . l - the number of curves
669: . names - the names of each curve to be used in displaying the legend. May be 'NULL'
670: . x - horizontal screen coordinate of the upper left corner of window, or use `PETSC_DECIDE`
671: . y - vertical screen coordinate of the upper left corner of window, or use `PETSC_DECIDE`
672: . 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`
673: - 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`
675: Level: developer
677: .seealso: `PetscViewer()`, `PETSCVIEWERDRAW`, `PetscViewerDrawGetDrawLG()`, `PetscViewerDrawOpen()`, `PetscViewerDrawSetInfo()`
678: @*/
679: 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
680: {
681: PetscDrawAxis axis;
682: PetscDrawLG lg;
684: PetscFunctionBegin;
685: PetscCall(PetscViewerSetType(viewer, PETSCVIEWERDRAW));
686: PetscCall(PetscViewerDrawSetInfo(viewer, host, title, x, y, m, n));
687: PetscCall(PetscViewerDrawGetDrawLG(viewer, 0, &lg));
688: if (names) PetscCall(PetscDrawLGSetLegend(lg, names));
689: PetscCall(PetscDrawLGSetFromOptions(lg));
690: PetscCall(PetscDrawLGGetAxis(lg, &axis));
691: PetscCall(PetscDrawAxisSetLabels(axis, "Convergence", "Iteration", metric));
692: PetscFunctionReturn(PETSC_SUCCESS);
693: }