Actual source code: drawv.c

  1: #include <../src/sys/classes/viewer/impls/draw/vdraw.h>

  3: static PetscErrorCode PetscViewerDestroy_Draw(PetscViewer v)
  4: {
  5:   PetscInt          i;
  6:   PetscViewer_Draw *vdraw = (PetscViewer_Draw *)v->data;

  8:   PetscFunctionBegin;
  9:   PetscCheck(!vdraw->singleton_made, PETSC_COMM_SELF, PETSC_ERR_ORDER, "Destroying PetscViewer without first restoring singleton");
 10:   for (i = 0; i < vdraw->draw_max; i++) {
 11:     PetscCall(PetscDrawAxisDestroy(&vdraw->drawaxis[i]));
 12:     PetscCall(PetscDrawLGDestroy(&vdraw->drawlg[i]));
 13:     PetscCall(PetscDrawDestroy(&vdraw->draw[i]));
 14:   }
 15:   PetscCall(PetscFree(vdraw->display));
 16:   PetscCall(PetscFree(vdraw->title));
 17:   PetscCall(PetscFree3(vdraw->draw, vdraw->drawlg, vdraw->drawaxis));
 18:   PetscCall(PetscFree(vdraw->bounds));
 19:   PetscCall(PetscFree(vdraw->drawtype));
 20:   PetscCall(PetscFree(v->data));
 21:   PetscFunctionReturn(PETSC_SUCCESS);
 22: }

 24: static PetscErrorCode PetscViewerFlush_Draw(PetscViewer v)
 25: {
 26:   PetscViewer_Draw *vdraw = (PetscViewer_Draw *)v->data;

 28:   PetscFunctionBegin;
 29:   for (PetscInt i = 0; i < vdraw->draw_max; i++) {
 30:     if (vdraw->draw[i]) PetscCall(PetscDrawFlush(vdraw->draw[i]));
 31:   }
 32:   PetscFunctionReturn(PETSC_SUCCESS);
 33: }

 35: /*@
 36:   PetscViewerDrawBaseAdd - add to the base integer that is added to the `windownumber` passed to `PetscViewerDrawGetDraw()`

 38:   Logically Collective

 40:   Input Parameters:
 41: + viewer       - the `PetscViewer` (created with `PetscViewerDrawOpen()`)
 42: - windownumber - how much to add to the base

 44:   Level: developer

 46:   Note:
 47:   A `PETSCVIEWERDRAW` may have multiple `PetscDraw` subwindows, this increases the number of the subwindow that is returned with `PetscViewerDrawGetDraw()`

 49: .seealso: [](sec_viewers), `PetscViewerDrawGetLG()`, `PetscViewerDrawGetAxis()`, `PetscViewerDrawOpen()`, `PetscViewerDrawGetDraw()`, `PetscViewerDrawBaseSet()`
 50: @*/
 51: PetscErrorCode PetscViewerDrawBaseAdd(PetscViewer viewer, PetscInt windownumber)
 52: {
 53:   PetscViewer_Draw *vdraw;
 54:   PetscBool         isdraw;

 56:   PetscFunctionBegin;
 59:   PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERDRAW, &isdraw));
 60:   PetscCheck(isdraw, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Must be draw type PetscViewer");
 61:   vdraw = (PetscViewer_Draw *)viewer->data;

 63:   PetscCheck(windownumber + vdraw->draw_base >= 0, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Resulting base %" PetscInt_FMT " cannot be negative", windownumber + vdraw->draw_base);
 64:   vdraw->draw_base += windownumber;
 65:   PetscFunctionReturn(PETSC_SUCCESS);
 66: }

 68: /*@
 69:   PetscViewerDrawBaseSet - sets the base integer that is added to the `windownumber` passed to `PetscViewerDrawGetDraw()`

 71:   Logically Collective

 73:   Input Parameters:
 74: + viewer       - the `PetscViewer` (created with `PetscViewerDrawOpen()`)
 75: - windownumber - value to set the base

 77:   Level: developer

 79:   Note:
 80:   A `PETSCVIEWERDRAW` may have multiple `PetscDraw` subwindows, this increases the number of the subwindow that is returned with `PetscViewerDrawGetDraw()`

 82: .seealso: [](sec_viewers), `PetscViewerDrawGetLG()`, `PetscViewerDrawGetAxis()`, `PetscViewerDrawOpen()`, `PetscViewerDrawGetDraw()`, `PetscViewerDrawBaseAdd()`
 83: @*/
 84: PetscErrorCode PetscViewerDrawBaseSet(PetscViewer viewer, PetscInt windownumber)
 85: {
 86:   PetscViewer_Draw *vdraw;
 87:   PetscBool         isdraw;

 89:   PetscFunctionBegin;
 92:   PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERDRAW, &isdraw));
 93:   PetscCheck(isdraw, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Must be draw type PetscViewer");
 94:   vdraw = (PetscViewer_Draw *)viewer->data;

 96:   PetscCheck(windownumber >= 0, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Resulting base %" PetscInt_FMT " cannot be negative", windownumber);
 97:   vdraw->draw_base = windownumber;
 98:   PetscFunctionReturn(PETSC_SUCCESS);
 99: }

101: /*@
102:   PetscViewerDrawResize - Set the default width and height (in pixels) for `PetscDraw` windows created by a `PETSCVIEWERDRAW` viewer.

104:   Logically Collective

106:   Input Parameters:
107: + v - the `PETSCVIEWERDRAW` viewer
108: . w - the new default window width in pixels; values less than 1 are ignored
109: - h - the new default window height in pixels; values less than 1 are ignored

111:   Level: intermediate

113:   Note:
114:   If `v` is not a `PETSCVIEWERDRAW` viewer, the call is a no-op.

116: .seealso: `PetscViewer`, `PETSCVIEWERDRAW`, `PetscViewerDrawOpen()`, `PetscViewerDrawSetInfo()`
117: @*/
118: PetscErrorCode PetscViewerDrawResize(PetscViewer v, 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:   if (w >= 1) vdraw->w = w;
130:   if (h >= 1) vdraw->h = h;
131:   PetscFunctionReturn(PETSC_SUCCESS);
132: }

134: /*@
135:   PetscViewerDrawSetInfo - Record the default display, title, position, and size to use for `PetscDraw` windows
136:   created by a `PETSCVIEWERDRAW` viewer.

138:   Logically Collective

140:   Input Parameters:
141: + v       - the `PETSCVIEWERDRAW` viewer
142: . display - the X display name, or `NULL` for the local machine
143: . title   - the window title, or `NULL`
144: . x       - the horizontal screen coordinate of the upper left corner (unused; retained for API symmetry)
145: . y       - the vertical screen coordinate of the upper left corner (unused; retained for API symmetry)
146: . w       - the default window width in pixels; values less than 1 are ignored
147: - h       - the default window height in pixels; values less than 1 are ignored

149:   Level: intermediate

151:   Note:
152:   If `v` is not a `PETSCVIEWERDRAW` viewer, the call is a no-op.

154: .seealso: `PetscViewer`, `PETSCVIEWERDRAW`, `PetscViewerDrawOpen()`, `PetscViewerDrawSetTitle()`, `PetscViewerDrawResize()`
155: @*/
156: PetscErrorCode PetscViewerDrawSetInfo(PetscViewer v, const char display[], const char title[], int x, int y, int w, int h)
157: {
158:   PetscViewer_Draw *vdraw;
159:   PetscBool         isdraw;

161:   PetscFunctionBegin;
163:   PetscCall(PetscObjectTypeCompare((PetscObject)v, PETSCVIEWERDRAW, &isdraw));
164:   if (!isdraw) PetscFunctionReturn(PETSC_SUCCESS);
165:   vdraw = (PetscViewer_Draw *)v->data;

167:   PetscCall(PetscStrallocpy(display, &vdraw->display));
168:   PetscCall(PetscStrallocpy(title, &vdraw->title));
169:   if (w >= 1) vdraw->w = w;
170:   if (h >= 1) vdraw->h = h;
171:   PetscFunctionReturn(PETSC_SUCCESS);
172: }

174: /*@
175:   PetscViewerDrawSetTitle - Set the default title used for `PetscDraw` windows created by a `PETSCVIEWERDRAW` viewer.

177:   Logically Collective

179:   Input Parameters:
180: + v     - the `PETSCVIEWERDRAW` viewer
181: - title - the window title, or `NULL` for no title

183:   Level: intermediate

185:   Note:
186:   If `v` is not a `PETSCVIEWERDRAW` viewer, the call is a no-op.

188: .seealso: `PetscViewer`, `PETSCVIEWERDRAW`, `PetscViewerDrawGetTitle()`, `PetscViewerDrawOpen()`, `PetscViewerDrawSetInfo()`
189: @*/
190: PetscErrorCode PetscViewerDrawSetTitle(PetscViewer v, const char title[])
191: {
192:   PetscViewer_Draw *vdraw;
193:   PetscBool         isdraw;

195:   PetscFunctionBegin;
197:   PetscCall(PetscObjectTypeCompare((PetscObject)v, PETSCVIEWERDRAW, &isdraw));
198:   if (!isdraw) PetscFunctionReturn(PETSC_SUCCESS);
199:   vdraw = (PetscViewer_Draw *)v->data;

201:   PetscCall(PetscFree(vdraw->title));
202:   PetscCall(PetscStrallocpy(title, &vdraw->title));
203:   PetscFunctionReturn(PETSC_SUCCESS);
204: }

206: /*@
207:   PetscViewerDrawGetTitle - Get the default title used for `PetscDraw` windows created by a `PETSCVIEWERDRAW` viewer.

209:   Not Collective; No Fortran Support

211:   Input Parameter:
212: . v - the `PETSCVIEWERDRAW` viewer

214:   Output Parameter:
215: . title - the window title (owned by the viewer; do not free)

217:   Level: intermediate

219: .seealso: `PetscViewer`, `PETSCVIEWERDRAW`, `PetscViewerDrawSetTitle()`, `PetscViewerDrawOpen()`, `PetscViewerDrawSetInfo()`
220: @*/
221: PetscErrorCode PetscViewerDrawGetTitle(PetscViewer v, const char *title[])
222: {
223:   PetscViewer_Draw *vdraw;
224:   PetscBool         isdraw;

226:   PetscFunctionBegin;
228:   PetscCall(PetscObjectTypeCompare((PetscObject)v, PETSCVIEWERDRAW, &isdraw));
229:   PetscCheck(isdraw, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Must be draw type PetscViewer");
230:   vdraw = (PetscViewer_Draw *)v->data;

232:   *title = vdraw->title;
233:   PetscFunctionReturn(PETSC_SUCCESS);
234: }

236: /*@
237:   PetscViewerDrawOpen - Opens a `PetscDraw` window for use as a `PetscViewer` with type
238:   `PETSCVIEWERDRAW`.

240:   Collective

242:   Input Parameters:
243: + comm    - communicator that will share window
244: . display - the X display on which to open, or `NULL` for the local machine
245: . title   - the title to put in the title bar, or `NULL` for no title
246: . x       - horizontal screen coordinate of the upper left corner of window, or use `PETSC_DECIDE`
247: . y       - vertical screen coordinate of the upper left corner of window, or use `PETSC_DECIDE`
248: . 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`
249: - 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`

251:   Output Parameter:
252: . viewer - the `PetscViewer`

254:   Options Database Keys:
255: + -draw_type        - use x or null
256: . -nox              - Disables all x-windows output
257: . -display name     - Specifies name of machine for the X display
258: . -geometry x,y,w,h - allows setting the window location and size
259: - -draw_pause pause - Sets time (in seconds) that the
260:                       program pauses after `PetscDrawPause()` has been called
261:                       (0 is default, -1 implies until user input).

263:   Level: beginner

265:   Notes:
266:   If you want to do graphics in this window, you must call `PetscViewerDrawGetDraw()` and
267:   perform the graphics on the `PetscDraw` object.

269:   Format options include\:
270: + `PETSC_VIEWER_DRAW_BASIC` - displays with basic format
271: - `PETSC_VIEWER_DRAW_LG`    - displays using a line graph

273:   Fortran Note:
274:   Whenever indicating null character data in a Fortran code,
275:   `PETSC_NULL_CHARACTER` must be employed. Thus, `PETSC_NULL_CHARACTER` can be
276:   used for the `display` and `title` input parameters.

278: .seealso: [](sec_viewers), `PETSCVIEWERDRAW`, `PetscDrawCreate()`, `PetscViewerDestroy()`, `PetscViewerDrawGetDraw()`, `PetscViewerCreate()`, `PETSC_VIEWER_DRAW_`,
279:           `PETSC_VIEWER_DRAW_WORLD`, `PETSC_VIEWER_DRAW_SELF`
280: @*/
281: PetscErrorCode PetscViewerDrawOpen(MPI_Comm comm, const char display[], const char title[], int x, int y, int w, int h, PetscViewer *viewer)
282: {
283:   PetscFunctionBegin;
284:   PetscCall(PetscViewerCreate(comm, viewer));
285:   PetscCall(PetscViewerSetType(*viewer, PETSCVIEWERDRAW));
286:   PetscCall(PetscViewerDrawSetInfo(*viewer, display, title, x, y, w, h));
287:   PetscFunctionReturn(PETSC_SUCCESS);
288: }

290: #include <petsc/private/drawimpl.h>

292: static PetscErrorCode PetscViewerGetSubViewer_Draw(PetscViewer viewer, MPI_Comm comm, PetscViewer *sviewer)
293: {
294:   PetscMPIInt       rank;
295:   PetscInt          i;
296:   PetscViewer_Draw *vdraw = (PetscViewer_Draw *)viewer->data, *svdraw;

298:   PetscFunctionBegin;
299:   PetscCheck(!vdraw->singleton_made, PETSC_COMM_SELF, PETSC_ERR_ORDER, "Trying to get SubViewer without first restoring previous");
300:   /* only processor zero can use the PetscViewer draw singleton */
301:   PetscCallMPI(MPI_Comm_rank(PetscObjectComm((PetscObject)viewer), &rank));
302:   if (rank == 0) {
303:     PetscMPIInt flg;
304:     PetscDraw   draw, sdraw;

306:     PetscCallMPI(MPI_Comm_compare(PETSC_COMM_SELF, comm, &flg));
307:     PetscCheck(flg == MPI_IDENT || flg == MPI_CONGRUENT, PETSC_COMM_SELF, PETSC_ERR_SUP, "PetscViewerGetSubViewer() for PETSCVIEWERDRAW requires a singleton MPI_Comm");
308:     PetscCall(PetscViewerCreate(comm, sviewer));
309:     PetscCall(PetscViewerSetType(*sviewer, PETSCVIEWERDRAW));
310:     svdraw             = (PetscViewer_Draw *)(*sviewer)->data;
311:     (*sviewer)->format = viewer->format;
312:     for (i = 0; i < vdraw->draw_max; i++) { /* XXX this is wrong if svdraw->draw_max (initially 5) < vdraw->draw_max */
313:       if (vdraw->draw[i]) PetscCall(PetscDrawGetSingleton(vdraw->draw[i], &svdraw->draw[i]));
314:     }
315:     PetscCall(PetscViewerDrawGetDraw(viewer, 0, &draw));
316:     PetscCall(PetscViewerDrawGetDraw(*sviewer, 0, &sdraw));
317:     if (draw->savefilename) {
318:       PetscCall(PetscDrawSetSave(sdraw, draw->savefilename));
319:       sdraw->savefilecount  = draw->savefilecount;
320:       sdraw->savesinglefile = draw->savesinglefile;
321:       sdraw->savemoviefps   = draw->savemoviefps;
322:       sdraw->saveonclear    = draw->saveonclear;
323:       sdraw->saveonflush    = draw->saveonflush;
324:     }
325:     if (draw->savefinalfilename) PetscCall(PetscDrawSetSaveFinalImage(sdraw, draw->savefinalfilename));
326:   } else {
327:     PetscDraw draw;
328:     PetscCall(PetscViewerDrawGetDraw(viewer, 0, &draw));
329:   }
330:   vdraw->singleton_made = PETSC_TRUE;
331:   PetscFunctionReturn(PETSC_SUCCESS);
332: }

334: static PetscErrorCode PetscViewerRestoreSubViewer_Draw(PetscViewer viewer, MPI_Comm comm, PetscViewer *sviewer)
335: {
336:   PetscMPIInt       rank;
337:   PetscInt          i;
338:   PetscViewer_Draw *vdraw = (PetscViewer_Draw *)viewer->data, *svdraw;

340:   PetscFunctionBegin;
341:   PetscCheck(vdraw->singleton_made, PETSC_COMM_SELF, PETSC_ERR_ORDER, "Trying to restore a singleton that was not gotten");
342:   PetscCallMPI(MPI_Comm_rank(PetscObjectComm((PetscObject)viewer), &rank));
343:   if (rank == 0) {
344:     PetscDraw draw, sdraw;

346:     PetscCall(PetscViewerDrawGetDraw(viewer, 0, &draw));
347:     PetscCall(PetscViewerDrawGetDraw(*sviewer, 0, &sdraw));
348:     if (draw->savefilename) {
349:       draw->savefilecount = sdraw->savefilecount;
350:       PetscCallMPI(MPI_Bcast(&draw->savefilecount, 1, MPIU_INT, 0, PetscObjectComm((PetscObject)draw)));
351:     }
352:     svdraw = (PetscViewer_Draw *)(*sviewer)->data;
353:     for (i = 0; i < vdraw->draw_max; i++) {
354:       if (vdraw->draw[i] && svdraw->draw[i]) PetscCall(PetscDrawRestoreSingleton(vdraw->draw[i], &svdraw->draw[i]));
355:     }
356:     PetscCall(PetscFree3(svdraw->draw, svdraw->drawlg, svdraw->drawaxis));
357:     PetscCall(PetscFree((*sviewer)->data));
358:     PetscCall(PetscHeaderDestroy(sviewer));
359:   } else {
360:     PetscDraw draw;

362:     PetscCall(PetscViewerDrawGetDraw(viewer, 0, &draw));
363:     if (draw->savefilename) PetscCallMPI(MPI_Bcast(&draw->savefilecount, 1, MPIU_INT, 0, PetscObjectComm((PetscObject)draw)));
364:   }

366:   vdraw->singleton_made = PETSC_FALSE;
367:   PetscFunctionReturn(PETSC_SUCCESS);
368: }

370: static PetscErrorCode PetscViewerSetFromOptions_Draw(PetscViewer v, PetscOptionItems PetscOptionsObject)
371: {
372:   PetscReal bounds[16];
373:   PetscInt  nbounds = 16;
374:   PetscBool flg;

376:   PetscFunctionBegin;
377:   PetscOptionsHeadBegin(PetscOptionsObject, "Draw PetscViewer Options");
378:   PetscCall(PetscOptionsRealArray("-draw_bounds", "Bounds to put on plots axis", "PetscViewerDrawSetBounds", bounds, &nbounds, &flg));
379:   if (flg) PetscCall(PetscViewerDrawSetBounds(v, nbounds / 2, bounds));
380:   PetscOptionsHeadEnd();
381:   PetscFunctionReturn(PETSC_SUCCESS);
382: }

384: static PetscErrorCode PetscViewerView_Draw(PetscViewer viewer, PetscViewer v)
385: {
386:   PetscDraw         draw;
387:   PetscInt          i;
388:   PetscViewer_Draw *vdraw = (PetscViewer_Draw *)viewer->data;
389:   PetscBool         isascii;

391:   PetscFunctionBegin;
392:   PetscCall(PetscObjectTypeCompare((PetscObject)v, PETSCVIEWERASCII, &isascii));
393:   if (isascii) PetscCall(PetscViewerASCIIPrintf(v, "Draw viewer is of type %s\n", vdraw->drawtype));
394:   /*  If the PetscViewer has just been created then no vdraw->draw yet
395:       exists so this will not actually call the viewer on any draws. */
396:   for (i = 0; i < vdraw->draw_base; i++) {
397:     if (vdraw->draw[i]) {
398:       PetscCall(PetscViewerDrawGetDraw(viewer, i, &draw));
399:       PetscCall(PetscDrawView(draw, v));
400:     }
401:   }
402:   PetscFunctionReturn(PETSC_SUCCESS);
403: }

405: /*MC
406:    PETSCVIEWERDRAW - A viewer that generates graphics, either to the screen or a file

408:   Level: beginner

410: .seealso: [](sec_viewers), `PetscViewerDrawOpen()`, `PetscViewerDrawGetDraw()`, `PETSC_VIEWER_DRAW_()`, `PETSC_VIEWER_DRAW_SELF`, `PETSC_VIEWER_DRAW_WORLD`,
411:           `PetscViewerCreate()`, `PetscViewerASCIIOpen()`, `PetscViewerBinaryOpen()`, `PETSCVIEWERBINARY`,
412:           `PetscViewerMatlabOpen()`, `VecView()`, `DMView()`, `PetscViewerMatlabPutArray()`, `PETSCVIEWERASCII`, `PETSCVIEWERMATLAB`,
413:           `PetscViewerFileSetName()`, `PetscViewerFileSetMode()`, `PetscViewerFormat`, `PetscViewerType`, `PetscViewerSetType()`
414: M*/
415: PETSC_EXTERN PetscErrorCode PetscViewerCreate_Draw(PetscViewer viewer)
416: {
417:   PetscViewer_Draw *vdraw;

419:   PetscFunctionBegin;
420:   PetscCall(PetscNew(&vdraw));
421:   viewer->data = (void *)vdraw;

423:   viewer->ops->flush            = PetscViewerFlush_Draw;
424:   viewer->ops->view             = PetscViewerView_Draw;
425:   viewer->ops->destroy          = PetscViewerDestroy_Draw;
426:   viewer->ops->setfromoptions   = PetscViewerSetFromOptions_Draw;
427:   viewer->ops->getsubviewer     = PetscViewerGetSubViewer_Draw;
428:   viewer->ops->restoresubviewer = PetscViewerRestoreSubViewer_Draw;

430:   /* these are created on the fly if requested */
431:   vdraw->draw_max  = 5;
432:   vdraw->draw_base = 0;
433:   vdraw->w         = PETSC_DECIDE;
434:   vdraw->h         = PETSC_DECIDE;

436:   PetscCall(PetscCalloc3(vdraw->draw_max, &vdraw->draw, vdraw->draw_max, &vdraw->drawlg, vdraw->draw_max, &vdraw->drawaxis));
437:   vdraw->singleton_made = PETSC_FALSE;
438:   PetscFunctionReturn(PETSC_SUCCESS);
439: }

441: /*@
442:   PetscViewerDrawClear - Clears a `PetscDraw` graphic associated with a `PetscViewer`.

444:   Not Collective

446:   Input Parameter:
447: . viewer - the `PetscViewer`

449:   Level: intermediate

451: .seealso: [](sec_viewers), `PETSCVIEWERDRAW`, `PetscViewerDrawOpen()`, `PetscViewerDrawGetDraw()`
452: @*/
453: PetscErrorCode PetscViewerDrawClear(PetscViewer viewer)
454: {
455:   PetscViewer_Draw *vdraw;
456:   PetscBool         isdraw;

458:   PetscFunctionBegin;
460:   PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERDRAW, &isdraw));
461:   if (!isdraw) PetscFunctionReturn(PETSC_SUCCESS);
462:   vdraw = (PetscViewer_Draw *)viewer->data;

464:   for (PetscInt i = 0; i < vdraw->draw_max; i++) {
465:     if (vdraw->draw[i]) PetscCall(PetscDrawClear(vdraw->draw[i]));
466:   }
467:   PetscFunctionReturn(PETSC_SUCCESS);
468: }

470: /*@
471:   PetscViewerDrawGetPause - Gets the pause value (how long to pause before an image is changed)  in the `PETSCVIEWERDRAW` `PetscViewer`

473:   Not Collective

475:   Input Parameter:
476: . viewer - the `PetscViewer`

478:   Output Parameter:
479: . pause - the pause value

481:   Level: intermediate

483: .seealso: [](sec_viewers), `PETSCVIEWERDRAW`, `PetscViewerDrawOpen()`, `PetscViewerDrawGetDraw()`
484: @*/
485: PetscErrorCode PetscViewerDrawGetPause(PetscViewer viewer, PetscReal *pause)
486: {
487:   PetscViewer_Draw *vdraw;
488:   PetscBool         isdraw;
489:   PetscDraw         draw;

491:   PetscFunctionBegin;
493:   PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERDRAW, &isdraw));
494:   if (!isdraw) {
495:     *pause = 0.0;
496:     PetscFunctionReturn(PETSC_SUCCESS);
497:   }
498:   vdraw = (PetscViewer_Draw *)viewer->data;

500:   for (PetscInt i = 0; i < vdraw->draw_max; i++) {
501:     if (vdraw->draw[i]) {
502:       PetscCall(PetscDrawGetPause(vdraw->draw[i], pause));
503:       PetscFunctionReturn(PETSC_SUCCESS);
504:     }
505:   }
506:   /* none exist yet so create one and get its pause */
507:   PetscCall(PetscViewerDrawGetDraw(viewer, 0, &draw));
508:   PetscCall(PetscDrawGetPause(draw, pause));
509:   PetscFunctionReturn(PETSC_SUCCESS);
510: }

512: /*@
513:   PetscViewerDrawSetPause - Sets a pause for each `PetscDraw` in the `PETSCVIEWERDRAW` `PetscViewer`

515:   Not Collective

517:   Input Parameters:
518: + viewer - the `PetscViewer`
519: - pause  - the pause value

521:   Level: intermediate

523: .seealso: [](sec_viewers), `PETSCVIEWERDRAW`, `PetscViewerDrawOpen()`, `PetscViewerDrawGetDraw()`
524: @*/
525: PetscErrorCode PetscViewerDrawSetPause(PetscViewer viewer, PetscReal pause)
526: {
527:   PetscViewer_Draw *vdraw;
528:   PetscBool         isdraw;

530:   PetscFunctionBegin;
532:   PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERDRAW, &isdraw));
533:   if (!isdraw) PetscFunctionReturn(PETSC_SUCCESS);
534:   vdraw = (PetscViewer_Draw *)viewer->data;

536:   vdraw->pause = pause;
537:   for (PetscInt i = 0; i < vdraw->draw_max; i++) {
538:     if (vdraw->draw[i]) PetscCall(PetscDrawSetPause(vdraw->draw[i], pause));
539:   }
540:   PetscFunctionReturn(PETSC_SUCCESS);
541: }

543: /*@
544:   PetscViewerDrawSetHold - Holds previous image when drawing new image in a `PETSCVIEWERDRAW`

546:   Not Collective

548:   Input Parameters:
549: + viewer - the `PetscViewer`
550: - hold   - `PETSC_TRUE` indicates to hold the previous image

552:   Level: intermediate

554: .seealso: [](sec_viewers), `PETSCVIEWERDRAW`, `PetscViewerDrawOpen()`, `PetscViewerDrawGetDraw()`
555: @*/
556: PetscErrorCode PetscViewerDrawSetHold(PetscViewer viewer, PetscBool hold)
557: {
558:   PetscViewer_Draw *vdraw;
559:   PetscBool         isdraw;

561:   PetscFunctionBegin;
563:   PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERDRAW, &isdraw));
564:   if (!isdraw) PetscFunctionReturn(PETSC_SUCCESS);
565:   vdraw = (PetscViewer_Draw *)viewer->data;

567:   vdraw->hold = hold;
568:   PetscFunctionReturn(PETSC_SUCCESS);
569: }

571: /*@
572:   PetscViewerDrawGetHold - Checks if the `PETSCVIEWERDRAW` `PetscViewer` holds previous image when drawing new image

574:   Not Collective

576:   Input Parameter:
577: . viewer - the `PetscViewer`

579:   Output Parameter:
580: . hold - indicates to hold or not

582:   Level: intermediate

584: .seealso: [](sec_viewers), `PETSCVIEWERDRAW`, `PetscViewerDrawOpen()`, `PetscViewerDrawGetDraw()`
585: @*/
586: PetscErrorCode PetscViewerDrawGetHold(PetscViewer viewer, PetscBool *hold)
587: {
588:   PetscViewer_Draw *vdraw;
589:   PetscBool         isdraw;

591:   PetscFunctionBegin;
593:   PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERDRAW, &isdraw));
594:   if (!isdraw) {
595:     *hold = PETSC_FALSE;
596:     PetscFunctionReturn(PETSC_SUCCESS);
597:   }
598:   vdraw = (PetscViewer_Draw *)viewer->data;

600:   *hold = vdraw->hold;
601:   PetscFunctionReturn(PETSC_SUCCESS);
602: }

604: /*
605:     The variable Petsc_Viewer_Draw_keyval is used to indicate an MPI attribute that
606:   is attached to a communicator, in this case the attribute is a PetscViewer.
607: */
608: PetscMPIInt Petsc_Viewer_Draw_keyval = MPI_KEYVAL_INVALID;

610: /*@
611:    PETSC_VIEWER_DRAW_ - Creates a window `PETSCVIEWERDRAW` `PetscViewer` shared by all processors
612:                      in an MPI communicator.

614:    Collective

616:    Input Parameter:
617: .  comm - the MPI communicator to share the window `PetscViewer`

619:    Level: intermediate

621:    Notes:
622:    This object is destroyed in `PetscFinalize()`, `PetscViewerDestroy()` should never be called on it

624:    Unlike almost all other PETSc routines, `PETSC_VIEWER_DRAW_()` does not return
625:    an error code.  The window is usually used in the form
626: .vb
627:    XXXView(XXX object, PETSC_VIEWER_DRAW_(comm));
628: .ve

630: .seealso: [](sec_viewers), `PETSCVIEWERDRAW`, `PetscViewer`, `PETSC_VIEWER_DRAW_WORLD`, `PETSC_VIEWER_DRAW_SELF`, `PetscViewerDrawOpen()`,
631: @*/
632: PetscViewer PETSC_VIEWER_DRAW_(MPI_Comm comm)
633: {
634:   PetscMPIInt iflg;
635:   PetscViewer viewer;
636:   MPI_Comm    ncomm;

638:   PetscFunctionBegin;
639:   PetscCallNull(PetscCommDuplicate(comm, &ncomm, NULL));
640:   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));
641:   PetscCallMPINull(MPI_Comm_get_attr(ncomm, Petsc_Viewer_Draw_keyval, (void **)&viewer, &iflg));
642:   if (!iflg) { /* PetscViewer not yet created */
643:     PetscCallNull(PetscViewerDrawOpen(ncomm, NULL, NULL, PETSC_DECIDE, PETSC_DECIDE, 300, 300, &viewer));
644:     PetscCallNull(PetscObjectRegisterDestroy((PetscObject)viewer));
645:     PetscCallMPINull(MPI_Comm_set_attr(ncomm, Petsc_Viewer_Draw_keyval, (void *)viewer));
646:   }
647:   PetscCallNull(PetscCommDestroy(&ncomm));
648:   PetscFunctionReturn(viewer);
649: }

651: /*@
652:   PetscViewerDrawSetBounds - sets the upper and lower bounds to be used in plotting in a `PETSCVIEWERDRAW` `PetscViewer`

654:   Collective

656:   Input Parameters:
657: + viewer  - the `PetscViewer` (created with `PetscViewerDrawOpen()`)
658: . nbounds - number of plots that can be made with this viewer, for example the dof passed to `DMDACreate()`
659: - 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, .....

661:   Options Database Key:
662: . -draw_bounds  minF0,maxF0,minF1,maxF1 - the lower left and upper right bounds

664:   Level: intermediate

666:   Note:
667:   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
668:   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
669:   this viewer. Otherwise the color to physical value meaning changes with each new image if this is not set.

671: .seealso: [](sec_viewers), `PETSCVIEWERDRAW`, `PetscViewerDrawGetLG()`, `PetscViewerDrawGetAxis()`, `PetscViewerDrawOpen()`
672: @*/
673: PetscErrorCode PetscViewerDrawSetBounds(PetscViewer viewer, PetscInt nbounds, const PetscReal *bounds)
674: {
675:   PetscViewer_Draw *vdraw;
676:   PetscBool         isdraw;

678:   PetscFunctionBegin;
680:   PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERDRAW, &isdraw));
681:   if (!isdraw) PetscFunctionReturn(PETSC_SUCCESS);
682:   vdraw = (PetscViewer_Draw *)viewer->data;

684:   vdraw->nbounds = nbounds;
685:   PetscCall(PetscFree(vdraw->bounds));
686:   PetscCall(PetscMalloc1(2 * nbounds, &vdraw->bounds));
687:   PetscCall(PetscArraycpy(vdraw->bounds, bounds, 2 * nbounds));
688:   PetscFunctionReturn(PETSC_SUCCESS);
689: }

691: /*@
692:   PetscViewerDrawGetBounds - gets the upper and lower bounds to be used in plotting set with `PetscViewerDrawSetBounds()`

694:   Collective

696:   Input Parameter:
697: . viewer - the `PetscViewer` (created with `PetscViewerDrawOpen()`)

699:   Output Parameters:
700: + nbounds - number of plots that can be made with this viewer, for example the dof passed to `DMDACreate()`
701: - 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, .....

703:   Level: intermediate

705: .seealso: [](sec_viewers), `PETSCVIEWERDRAW`, `PetscViewerDrawGetLG()`, `PetscViewerDrawGetAxis()`, `PetscViewerDrawOpen()`, `PetscViewerDrawSetBounds()`
706: @*/
707: PetscErrorCode PetscViewerDrawGetBounds(PetscViewer viewer, PetscInt *nbounds, const PetscReal *bounds[])
708: {
709:   PetscViewer_Draw *vdraw;
710:   PetscBool         isdraw;

712:   PetscFunctionBegin;
714:   PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERDRAW, &isdraw));
715:   if (!isdraw) {
716:     if (nbounds) *nbounds = 0;
717:     if (bounds) *bounds = NULL;
718:     PetscFunctionReturn(PETSC_SUCCESS);
719:   }
720:   vdraw = (PetscViewer_Draw *)viewer->data;

722:   if (nbounds) *nbounds = vdraw->nbounds;
723:   if (bounds) *bounds = vdraw->bounds;
724:   PetscFunctionReturn(PETSC_SUCCESS);
725: }

727: /*@
728:   PetscViewerMonitorLGSetUp - sets up a viewer to be used by line graph monitoring routines such as `KSPMonitorResidualDrawLG()`

730:   Collective

732:   Input Parameters:
733: + viewer - the viewer in which to display the line graphs, it not a `PETSCVIEWERDRAW` it will set to that `PetscViewerType`
734: . host   - the host to open the window on, `NULL` indicates the local host
735: . title  - the title at the top of the window
736: . metric - the label above the graph
737: . l      - the number of curves
738: . names  - the names of each curve to be used in displaying the legend. May be `NULL`
739: . x      - horizontal screen coordinate of the upper left corner of window, or use `PETSC_DECIDE`
740: . y      - vertical screen coordinate of the upper left corner of window, or use `PETSC_DECIDE`
741: . 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`
742: - 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`

744:   Level: developer

746: .seealso: `PetscViewer()`, `PETSCVIEWERDRAW`, `PetscViewerDrawGetDrawLG()`, `PetscViewerDrawOpen()`, `PetscViewerDrawSetInfo()`
747: @*/
748: 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
749: {
750:   PetscDrawAxis axis;
751:   PetscDrawLG   lg;

753:   PetscFunctionBegin;
754:   PetscCall(PetscViewerSetType(viewer, PETSCVIEWERDRAW));
755:   PetscCall(PetscViewerDrawSetInfo(viewer, host, title, x, y, m, n));
756:   PetscCall(PetscViewerDrawGetDrawLG(viewer, 0, &lg));
757:   if (names) PetscCall(PetscDrawLGSetLegend(lg, names));
758:   PetscCall(PetscDrawLGSetFromOptions(lg));
759:   PetscCall(PetscDrawLGGetAxis(lg, &axis));
760:   PetscCall(PetscDrawAxisSetLabels(axis, "Convergence", "Iteration", metric));
761:   PetscFunctionReturn(PETSC_SUCCESS);
762: }