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 Note:
206: Whenever indicating null character data in a Fortran code,
207: `PETSC_NULL_CHARACTER` must be employed. Thus, `PETSC_NULL_CHARACTER` can be
208: used for the `display` and `title` input parameters.
210: .seealso: [](sec_viewers), `PETSCVIEWERDRAW`, `PetscDrawCreate()`, `PetscViewerDestroy()`, `PetscViewerDrawGetDraw()`, `PetscViewerCreate()`, `PETSC_VIEWER_DRAW_`,
211: `PETSC_VIEWER_DRAW_WORLD`, `PETSC_VIEWER_DRAW_SELF`
212: @*/
213: PetscErrorCode PetscViewerDrawOpen(MPI_Comm comm, const char display[], const char title[], int x, int y, int w, int h, PetscViewer *viewer)
214: {
215: PetscFunctionBegin;
216: PetscCall(PetscViewerCreate(comm, viewer));
217: PetscCall(PetscViewerSetType(*viewer, PETSCVIEWERDRAW));
218: PetscCall(PetscViewerDrawSetInfo(*viewer, display, title, x, y, w, h));
219: PetscFunctionReturn(PETSC_SUCCESS);
220: }
222: #include <petsc/private/drawimpl.h>
224: static PetscErrorCode PetscViewerGetSubViewer_Draw(PetscViewer viewer, MPI_Comm comm, PetscViewer *sviewer)
225: {
226: PetscMPIInt rank;
227: PetscInt i;
228: PetscViewer_Draw *vdraw = (PetscViewer_Draw *)viewer->data, *svdraw;
230: PetscFunctionBegin;
231: PetscCheck(!vdraw->singleton_made, PETSC_COMM_SELF, PETSC_ERR_ORDER, "Trying to get SubViewer without first restoring previous");
232: /* only processor zero can use the PetscViewer draw singleton */
233: PetscCallMPI(MPI_Comm_rank(PetscObjectComm((PetscObject)viewer), &rank));
234: if (rank == 0) {
235: PetscMPIInt flg;
236: PetscDraw draw, sdraw;
238: PetscCallMPI(MPI_Comm_compare(PETSC_COMM_SELF, comm, &flg));
239: PetscCheck(flg == MPI_IDENT || flg == MPI_CONGRUENT, PETSC_COMM_SELF, PETSC_ERR_SUP, "PetscViewerGetSubViewer() for PETSCVIEWERDRAW requires a singleton MPI_Comm");
240: PetscCall(PetscViewerCreate(comm, sviewer));
241: PetscCall(PetscViewerSetType(*sviewer, PETSCVIEWERDRAW));
242: svdraw = (PetscViewer_Draw *)(*sviewer)->data;
243: (*sviewer)->format = viewer->format;
244: for (i = 0; i < vdraw->draw_max; i++) { /* XXX this is wrong if svdraw->draw_max (initially 5) < vdraw->draw_max */
245: if (vdraw->draw[i]) PetscCall(PetscDrawGetSingleton(vdraw->draw[i], &svdraw->draw[i]));
246: }
247: PetscCall(PetscViewerDrawGetDraw(viewer, 0, &draw));
248: PetscCall(PetscViewerDrawGetDraw(*sviewer, 0, &sdraw));
249: if (draw->savefilename) {
250: PetscCall(PetscDrawSetSave(sdraw, draw->savefilename));
251: sdraw->savefilecount = draw->savefilecount;
252: sdraw->savesinglefile = draw->savesinglefile;
253: sdraw->savemoviefps = draw->savemoviefps;
254: sdraw->saveonclear = draw->saveonclear;
255: sdraw->saveonflush = draw->saveonflush;
256: }
257: if (draw->savefinalfilename) PetscCall(PetscDrawSetSaveFinalImage(sdraw, draw->savefinalfilename));
258: } else {
259: PetscDraw draw;
260: PetscCall(PetscViewerDrawGetDraw(viewer, 0, &draw));
261: }
262: vdraw->singleton_made = PETSC_TRUE;
263: PetscFunctionReturn(PETSC_SUCCESS);
264: }
266: static PetscErrorCode PetscViewerRestoreSubViewer_Draw(PetscViewer viewer, MPI_Comm comm, PetscViewer *sviewer)
267: {
268: PetscMPIInt rank;
269: PetscInt i;
270: PetscViewer_Draw *vdraw = (PetscViewer_Draw *)viewer->data, *svdraw;
272: PetscFunctionBegin;
273: PetscCheck(vdraw->singleton_made, PETSC_COMM_SELF, PETSC_ERR_ORDER, "Trying to restore a singleton that was not gotten");
274: PetscCallMPI(MPI_Comm_rank(PetscObjectComm((PetscObject)viewer), &rank));
275: if (rank == 0) {
276: PetscDraw draw, sdraw;
278: PetscCall(PetscViewerDrawGetDraw(viewer, 0, &draw));
279: PetscCall(PetscViewerDrawGetDraw(*sviewer, 0, &sdraw));
280: if (draw->savefilename) {
281: draw->savefilecount = sdraw->savefilecount;
282: PetscCallMPI(MPI_Bcast(&draw->savefilecount, 1, MPIU_INT, 0, PetscObjectComm((PetscObject)draw)));
283: }
284: svdraw = (PetscViewer_Draw *)(*sviewer)->data;
285: for (i = 0; i < vdraw->draw_max; i++) {
286: if (vdraw->draw[i] && svdraw->draw[i]) PetscCall(PetscDrawRestoreSingleton(vdraw->draw[i], &svdraw->draw[i]));
287: }
288: PetscCall(PetscFree3(svdraw->draw, svdraw->drawlg, svdraw->drawaxis));
289: PetscCall(PetscFree((*sviewer)->data));
290: PetscCall(PetscHeaderDestroy(sviewer));
291: } else {
292: PetscDraw draw;
294: PetscCall(PetscViewerDrawGetDraw(viewer, 0, &draw));
295: if (draw->savefilename) PetscCallMPI(MPI_Bcast(&draw->savefilecount, 1, MPIU_INT, 0, PetscObjectComm((PetscObject)draw)));
296: }
298: vdraw->singleton_made = PETSC_FALSE;
299: PetscFunctionReturn(PETSC_SUCCESS);
300: }
302: static PetscErrorCode PetscViewerSetFromOptions_Draw(PetscViewer v, PetscOptionItems PetscOptionsObject)
303: {
304: PetscReal bounds[16];
305: PetscInt nbounds = 16;
306: PetscBool flg;
308: PetscFunctionBegin;
309: PetscOptionsHeadBegin(PetscOptionsObject, "Draw PetscViewer Options");
310: PetscCall(PetscOptionsRealArray("-draw_bounds", "Bounds to put on plots axis", "PetscViewerDrawSetBounds", bounds, &nbounds, &flg));
311: if (flg) PetscCall(PetscViewerDrawSetBounds(v, nbounds / 2, bounds));
312: PetscOptionsHeadEnd();
313: PetscFunctionReturn(PETSC_SUCCESS);
314: }
316: static PetscErrorCode PetscViewerView_Draw(PetscViewer viewer, PetscViewer v)
317: {
318: PetscDraw draw;
319: PetscInt i;
320: PetscViewer_Draw *vdraw = (PetscViewer_Draw *)viewer->data;
321: PetscBool iascii;
323: PetscFunctionBegin;
324: PetscCall(PetscObjectTypeCompare((PetscObject)v, PETSCVIEWERASCII, &iascii));
325: if (iascii) PetscCall(PetscViewerASCIIPrintf(v, "Draw viewer is of type %s\n", vdraw->drawtype));
326: /* If the PetscViewer has just been created then no vdraw->draw yet
327: exists so this will not actually call the viewer on any draws. */
328: for (i = 0; i < vdraw->draw_base; i++) {
329: if (vdraw->draw[i]) {
330: PetscCall(PetscViewerDrawGetDraw(viewer, i, &draw));
331: PetscCall(PetscDrawView(draw, v));
332: }
333: }
334: PetscFunctionReturn(PETSC_SUCCESS);
335: }
337: /*MC
338: PETSCVIEWERDRAW - A viewer that generates graphics, either to the screen or a file
340: Level: beginner
342: .seealso: [](sec_viewers), `PetscViewerDrawOpen()`, `PetscViewerDrawGetDraw()`, `PETSC_VIEWER_DRAW_()`, `PETSC_VIEWER_DRAW_SELF`, `PETSC_VIEWER_DRAW_WORLD`,
343: `PetscViewerCreate()`, `PetscViewerASCIIOpen()`, `PetscViewerBinaryOpen()`, `PETSCVIEWERBINARY`,
344: `PetscViewerMatlabOpen()`, `VecView()`, `DMView()`, `PetscViewerMatlabPutArray()`, `PETSCVIEWERASCII`, `PETSCVIEWERMATLAB`,
345: `PetscViewerFileSetName()`, `PetscViewerFileSetMode()`, `PetscViewerFormat`, `PetscViewerType`, `PetscViewerSetType()`
346: M*/
347: PETSC_EXTERN PetscErrorCode PetscViewerCreate_Draw(PetscViewer viewer)
348: {
349: PetscViewer_Draw *vdraw;
351: PetscFunctionBegin;
352: PetscCall(PetscNew(&vdraw));
353: viewer->data = (void *)vdraw;
355: viewer->ops->flush = PetscViewerFlush_Draw;
356: viewer->ops->view = PetscViewerView_Draw;
357: viewer->ops->destroy = PetscViewerDestroy_Draw;
358: viewer->ops->setfromoptions = PetscViewerSetFromOptions_Draw;
359: viewer->ops->getsubviewer = PetscViewerGetSubViewer_Draw;
360: viewer->ops->restoresubviewer = PetscViewerRestoreSubViewer_Draw;
362: /* these are created on the fly if requested */
363: vdraw->draw_max = 5;
364: vdraw->draw_base = 0;
365: vdraw->w = PETSC_DECIDE;
366: vdraw->h = PETSC_DECIDE;
368: PetscCall(PetscCalloc3(vdraw->draw_max, &vdraw->draw, vdraw->draw_max, &vdraw->drawlg, vdraw->draw_max, &vdraw->drawaxis));
369: vdraw->singleton_made = PETSC_FALSE;
370: PetscFunctionReturn(PETSC_SUCCESS);
371: }
373: /*@
374: PetscViewerDrawClear - Clears a `PetscDraw` graphic associated with a `PetscViewer`.
376: Not Collective
378: Input Parameter:
379: . viewer - the `PetscViewer`
381: Level: intermediate
383: .seealso: [](sec_viewers), `PETSCVIEWERDRAW`, `PetscViewerDrawOpen()`, `PetscViewerDrawGetDraw()`,
384: @*/
385: PetscErrorCode PetscViewerDrawClear(PetscViewer viewer)
386: {
387: PetscViewer_Draw *vdraw;
388: PetscBool isdraw;
389: PetscInt i;
391: PetscFunctionBegin;
393: PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERDRAW, &isdraw));
394: if (!isdraw) PetscFunctionReturn(PETSC_SUCCESS);
395: vdraw = (PetscViewer_Draw *)viewer->data;
397: for (i = 0; i < vdraw->draw_max; i++) {
398: if (vdraw->draw[i]) PetscCall(PetscDrawClear(vdraw->draw[i]));
399: }
400: PetscFunctionReturn(PETSC_SUCCESS);
401: }
403: /*@
404: PetscViewerDrawGetPause - Gets the pause value (how long to pause before an image is changed) in the `PETSCVIEWERDRAW` `PetscViewer`
406: Not Collective
408: Input Parameter:
409: . viewer - the `PetscViewer`
411: Output Parameter:
412: . pause - the pause value
414: Level: intermediate
416: .seealso: [](sec_viewers), `PETSCVIEWERDRAW`, `PetscViewerDrawOpen()`, `PetscViewerDrawGetDraw()`,
417: @*/
418: PetscErrorCode PetscViewerDrawGetPause(PetscViewer viewer, PetscReal *pause)
419: {
420: PetscViewer_Draw *vdraw;
421: PetscBool isdraw;
422: PetscInt i;
423: PetscDraw draw;
425: PetscFunctionBegin;
427: PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERDRAW, &isdraw));
428: if (!isdraw) {
429: *pause = 0.0;
430: PetscFunctionReturn(PETSC_SUCCESS);
431: }
432: vdraw = (PetscViewer_Draw *)viewer->data;
434: for (i = 0; i < vdraw->draw_max; i++) {
435: if (vdraw->draw[i]) {
436: PetscCall(PetscDrawGetPause(vdraw->draw[i], pause));
437: PetscFunctionReturn(PETSC_SUCCESS);
438: }
439: }
440: /* none exist yet so create one and get its pause */
441: PetscCall(PetscViewerDrawGetDraw(viewer, 0, &draw));
442: PetscCall(PetscDrawGetPause(draw, pause));
443: PetscFunctionReturn(PETSC_SUCCESS);
444: }
446: /*@
447: PetscViewerDrawSetPause - Sets a pause for each `PetscDraw` in the `PETSCVIEWERDRAW` `PetscViewer`
449: Not Collective
451: Input Parameters:
452: + viewer - the `PetscViewer`
453: - pause - the pause value
455: Level: intermediate
457: .seealso: [](sec_viewers), `PETSCVIEWERDRAW`, `PetscViewerDrawOpen()`, `PetscViewerDrawGetDraw()`,
458: @*/
459: PetscErrorCode PetscViewerDrawSetPause(PetscViewer viewer, PetscReal pause)
460: {
461: PetscViewer_Draw *vdraw;
462: PetscBool isdraw;
463: PetscInt i;
465: PetscFunctionBegin;
467: PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERDRAW, &isdraw));
468: if (!isdraw) PetscFunctionReturn(PETSC_SUCCESS);
469: vdraw = (PetscViewer_Draw *)viewer->data;
471: vdraw->pause = pause;
472: for (i = 0; i < vdraw->draw_max; i++) {
473: if (vdraw->draw[i]) PetscCall(PetscDrawSetPause(vdraw->draw[i], pause));
474: }
475: PetscFunctionReturn(PETSC_SUCCESS);
476: }
478: /*@
479: PetscViewerDrawSetHold - Holds previous image when drawing new image in a `PETSCVIEWERDRAW`
481: Not Collective
483: Input Parameters:
484: + viewer - the `PetscViewer`
485: - hold - `PETSC_TRUE` indicates to hold the previous image
487: Level: intermediate
489: .seealso: [](sec_viewers), `PETSCVIEWERDRAW`, `PetscViewerDrawOpen()`, `PetscViewerDrawGetDraw()`,
490: @*/
491: PetscErrorCode PetscViewerDrawSetHold(PetscViewer viewer, PetscBool hold)
492: {
493: PetscViewer_Draw *vdraw;
494: PetscBool isdraw;
496: PetscFunctionBegin;
498: PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERDRAW, &isdraw));
499: if (!isdraw) PetscFunctionReturn(PETSC_SUCCESS);
500: vdraw = (PetscViewer_Draw *)viewer->data;
502: vdraw->hold = hold;
503: PetscFunctionReturn(PETSC_SUCCESS);
504: }
506: /*@
507: PetscViewerDrawGetHold - Checks if the `PETSCVIEWERDRAW` `PetscViewer` holds previous image when drawing new image
509: Not Collective
511: Input Parameter:
512: . viewer - the `PetscViewer`
514: Output Parameter:
515: . hold - indicates to hold or not
517: Level: intermediate
519: .seealso: [](sec_viewers), `PETSCVIEWERDRAW`, `PetscViewerDrawOpen()`, `PetscViewerDrawGetDraw()`,
520: @*/
521: PetscErrorCode PetscViewerDrawGetHold(PetscViewer viewer, PetscBool *hold)
522: {
523: PetscViewer_Draw *vdraw;
524: PetscBool isdraw;
526: PetscFunctionBegin;
528: PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERDRAW, &isdraw));
529: if (!isdraw) {
530: *hold = PETSC_FALSE;
531: PetscFunctionReturn(PETSC_SUCCESS);
532: }
533: vdraw = (PetscViewer_Draw *)viewer->data;
535: *hold = vdraw->hold;
536: PetscFunctionReturn(PETSC_SUCCESS);
537: }
539: /*
540: The variable Petsc_Viewer_Draw_keyval is used to indicate an MPI attribute that
541: is attached to a communicator, in this case the attribute is a PetscViewer.
542: */
543: PetscMPIInt Petsc_Viewer_Draw_keyval = MPI_KEYVAL_INVALID;
545: /*@C
546: PETSC_VIEWER_DRAW_ - Creates a window `PETSCVIEWERDRAW` `PetscViewer` shared by all processors
547: in an MPI communicator.
549: Collective
551: Input Parameter:
552: . comm - the MPI communicator to share the window `PetscViewer`
554: Level: intermediate
556: Notes:
557: This object is destroyed in `PetscFinalize()`, `PetscViewerDestroy()` should never be called on it
559: Unlike almost all other PETSc routines, `PETSC_VIEWER_DRAW_()` does not return
560: an error code. The window is usually used in the form
561: .vb
562: XXXView(XXX object, PETSC_VIEWER_DRAW_(comm));
563: .ve
565: .seealso: [](sec_viewers), `PETSCVIEWERDRAW`, `PetscViewer`, `PETSC_VIEWER_DRAW_WORLD`, `PETSC_VIEWER_DRAW_SELF`, `PetscViewerDrawOpen()`,
566: @*/
567: PetscViewer PETSC_VIEWER_DRAW_(MPI_Comm comm)
568: {
569: PetscMPIInt flag;
570: PetscViewer viewer;
571: MPI_Comm ncomm;
573: PetscFunctionBegin;
574: PetscCallNull(PetscCommDuplicate(comm, &ncomm, NULL));
575: 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)); }
576: PetscCallMPINull(MPI_Comm_get_attr(ncomm, Petsc_Viewer_Draw_keyval, (void **)&viewer, &flag));
577: if (!flag) { /* PetscViewer not yet created */
578: PetscCallNull(PetscViewerDrawOpen(ncomm, NULL, NULL, PETSC_DECIDE, PETSC_DECIDE, 300, 300, &viewer));
579: PetscCallNull(PetscObjectRegisterDestroy((PetscObject)viewer));
580: PetscCallMPINull(MPI_Comm_set_attr(ncomm, Petsc_Viewer_Draw_keyval, (void *)viewer));
581: }
582: PetscCallNull(PetscCommDestroy(&ncomm));
583: PetscFunctionReturn(viewer);
584: }
586: /*@
587: PetscViewerDrawSetBounds - sets the upper and lower bounds to be used in plotting in a `PETSCVIEWERDRAW` `PetscViewer`
589: Collective
591: Input Parameters:
592: + viewer - the `PetscViewer` (created with `PetscViewerDrawOpen()`)
593: . nbounds - number of plots that can be made with this viewer, for example the dof passed to `DMDACreate()`
594: - 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, .....
596: Options Database Key:
597: . -draw_bounds minF0,maxF0,minF1,maxF1 - the lower left and upper right bounds
599: Level: intermediate
601: Note:
602: 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
603: 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
604: this viewer. Otherwise the color to physical value meaning changes with each new image if this is not set.
606: .seealso: [](sec_viewers), `PETSCVIEWERDRAW`, `PetscViewerDrawGetLG()`, `PetscViewerDrawGetAxis()`, `PetscViewerDrawOpen()`
607: @*/
608: PetscErrorCode PetscViewerDrawSetBounds(PetscViewer viewer, PetscInt nbounds, const PetscReal *bounds)
609: {
610: PetscViewer_Draw *vdraw;
611: PetscBool isdraw;
613: PetscFunctionBegin;
615: PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERDRAW, &isdraw));
616: if (!isdraw) PetscFunctionReturn(PETSC_SUCCESS);
617: vdraw = (PetscViewer_Draw *)viewer->data;
619: vdraw->nbounds = nbounds;
620: PetscCall(PetscFree(vdraw->bounds));
621: PetscCall(PetscMalloc1(2 * nbounds, &vdraw->bounds));
622: PetscCall(PetscArraycpy(vdraw->bounds, bounds, 2 * nbounds));
623: PetscFunctionReturn(PETSC_SUCCESS);
624: }
626: /*@C
627: PetscViewerDrawGetBounds - gets the upper and lower bounds to be used in plotting set with `PetscViewerDrawSetBounds()`
629: Collective
631: Input Parameter:
632: . viewer - the `PetscViewer` (created with `PetscViewerDrawOpen()`)
634: Output Parameters:
635: + nbounds - number of plots that can be made with this viewer, for example the dof passed to `DMDACreate()`
636: - 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, .....
638: Level: intermediate
640: .seealso: [](sec_viewers), `PETSCVIEWERDRAW`, `PetscViewerDrawGetLG()`, `PetscViewerDrawGetAxis()`, `PetscViewerDrawOpen()`, `PetscViewerDrawSetBounds()`
641: @*/
642: PetscErrorCode PetscViewerDrawGetBounds(PetscViewer viewer, PetscInt *nbounds, const PetscReal *bounds[])
643: {
644: PetscViewer_Draw *vdraw;
645: PetscBool isdraw;
647: PetscFunctionBegin;
649: PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERDRAW, &isdraw));
650: if (!isdraw) {
651: if (nbounds) *nbounds = 0;
652: if (bounds) *bounds = NULL;
653: PetscFunctionReturn(PETSC_SUCCESS);
654: }
655: vdraw = (PetscViewer_Draw *)viewer->data;
657: if (nbounds) *nbounds = vdraw->nbounds;
658: if (bounds) *bounds = vdraw->bounds;
659: PetscFunctionReturn(PETSC_SUCCESS);
660: }
662: /*@C
663: PetscViewerMonitorLGSetUp - sets up a viewer to be used by line graph monitoring routines such as `KSPMonitorResidualDrawLG()`
665: Collective
667: Input Parameters:
668: + viewer - the viewer in which to display the line graphs, it not a `PETSCVIEWERDRAW` it will set to that `PetscViewerType`
669: . host - the host to open the window on, 'NULL' indicates the local host
670: . title - the title at the top of the window
671: . metric - the label above the graph
672: . l - the number of curves
673: . names - the names of each curve to be used in displaying the legend. May be 'NULL'
674: . x - horizontal screen coordinate of the upper left corner of window, or use `PETSC_DECIDE`
675: . y - vertical screen coordinate of the upper left corner of window, or use `PETSC_DECIDE`
676: . 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`
677: - 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`
679: Level: developer
681: .seealso: `PetscViewer()`, `PETSCVIEWERDRAW`, `PetscViewerDrawGetDrawLG()`, `PetscViewerDrawOpen()`, `PetscViewerDrawSetInfo()`
682: @*/
683: 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
684: {
685: PetscDrawAxis axis;
686: PetscDrawLG lg;
688: PetscFunctionBegin;
689: PetscCall(PetscViewerSetType(viewer, PETSCVIEWERDRAW));
690: PetscCall(PetscViewerDrawSetInfo(viewer, host, title, x, y, m, n));
691: PetscCall(PetscViewerDrawGetDrawLG(viewer, 0, &lg));
692: if (names) PetscCall(PetscDrawLGSetLegend(lg, names));
693: PetscCall(PetscDrawLGSetFromOptions(lg));
694: PetscCall(PetscDrawLGGetAxis(lg, &axis));
695: PetscCall(PetscDrawAxisSetLabels(axis, "Convergence", "Iteration", metric));
696: PetscFunctionReturn(PETSC_SUCCESS);
697: }