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: }