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: /*@
103:   PetscViewerDrawResize - Set the default width and height (in pixels) for `PetscDraw` windows created by a `PETSCVIEWERDRAW` viewer.

105:   Logically Collective

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

112:   Level: intermediate

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

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

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

139:   Logically Collective

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

150:   Level: intermediate

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

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

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

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

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

178:   Logically Collective

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

184:   Level: intermediate

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

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

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

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

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

210:   Not Collective; No Fortran Support

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

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

218:   Level: intermediate

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

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

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

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

241:   Collective

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

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

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

264:   Level: beginner

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

409:   Level: beginner

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

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

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

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

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

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

445:   Not Collective

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

450:   Level: intermediate

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

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

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

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

474:   Not Collective

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

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

482:   Level: intermediate

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

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

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

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

516:   Not Collective

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

522:   Level: intermediate

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

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

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

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

547:   Not Collective

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

553:   Level: intermediate

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

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

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

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

575:   Not Collective

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

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

583:   Level: intermediate

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

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

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

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

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

615:    Collective

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

620:    Level: intermediate

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

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

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

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

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

655:   Collective

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

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

665:   Level: intermediate

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

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

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

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

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

695:   Collective

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

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

704:   Level: intermediate

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

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

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

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

731:   Collective

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

745:   Level: developer

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

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