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 Notes:
206:   Whenever indicating null character data in a Fortran code,
207:   `PETSC_NULL_CHARACTER` must be employed; using NULL is not
208:   correct for character data!  Thus, `PETSC_NULL_CHARACTER` can be
209:   used for the display and title input parameters.

211: .seealso: [](sec_viewers), `PETSCVIEWERDRAW`, `PetscDrawCreate()`, `PetscViewerDestroy()`, `PetscViewerDrawGetDraw()`, `PetscViewerCreate()`, `PETSC_VIEWER_DRAW_`,
212:           `PETSC_VIEWER_DRAW_WORLD`, `PETSC_VIEWER_DRAW_SELF`
213: @*/
214: PetscErrorCode PetscViewerDrawOpen(MPI_Comm comm, const char display[], const char title[], int x, int y, int w, int h, PetscViewer *viewer)
215: {
216:   PetscFunctionBegin;
217:   PetscCall(PetscViewerCreate(comm, viewer));
218:   PetscCall(PetscViewerSetType(*viewer, PETSCVIEWERDRAW));
219:   PetscCall(PetscViewerDrawSetInfo(*viewer, display, title, x, y, w, h));
220:   PetscFunctionReturn(PETSC_SUCCESS);
221: }

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

225: static PetscErrorCode PetscViewerGetSubViewer_Draw(PetscViewer viewer, MPI_Comm comm, PetscViewer *sviewer)
226: {
227:   PetscMPIInt       rank;
228:   PetscInt          i;
229:   PetscViewer_Draw *vdraw = (PetscViewer_Draw *)viewer->data, *svdraw;

231:   PetscFunctionBegin;
232:   PetscCheck(!vdraw->singleton_made, PETSC_COMM_SELF, PETSC_ERR_ORDER, "Trying to get SubViewer without first restoring previous");
233:   /* only processor zero can use the PetscViewer draw singleton */
234:   PetscCallMPI(MPI_Comm_rank(PetscObjectComm((PetscObject)viewer), &rank));
235:   if (rank == 0) {
236:     PetscMPIInt flg;
237:     PetscDraw   draw, sdraw;

239:     PetscCallMPI(MPI_Comm_compare(PETSC_COMM_SELF, comm, &flg));
240:     PetscCheck(flg == MPI_IDENT || flg == MPI_CONGRUENT, PETSC_COMM_SELF, PETSC_ERR_SUP, "PetscViewerGetSubViewer() for PETSCVIEWERDRAW requires a singleton MPI_Comm");
241:     PetscCall(PetscViewerCreate(comm, sviewer));
242:     PetscCall(PetscViewerSetType(*sviewer, PETSCVIEWERDRAW));
243:     svdraw             = (PetscViewer_Draw *)(*sviewer)->data;
244:     (*sviewer)->format = viewer->format;
245:     for (i = 0; i < vdraw->draw_max; i++) { /* XXX this is wrong if svdraw->draw_max (initially 5) < vdraw->draw_max */
246:       if (vdraw->draw[i]) PetscCall(PetscDrawGetSingleton(vdraw->draw[i], &svdraw->draw[i]));
247:     }
248:     PetscCall(PetscViewerDrawGetDraw(viewer, 0, &draw));
249:     PetscCall(PetscViewerDrawGetDraw(*sviewer, 0, &sdraw));
250:     if (draw->savefilename) {
251:       PetscCall(PetscDrawSetSave(sdraw, draw->savefilename));
252:       sdraw->savefilecount  = draw->savefilecount;
253:       sdraw->savesinglefile = draw->savesinglefile;
254:       sdraw->savemoviefps   = draw->savemoviefps;
255:       sdraw->saveonclear    = draw->saveonclear;
256:       sdraw->saveonflush    = draw->saveonflush;
257:     }
258:     if (draw->savefinalfilename) PetscCall(PetscDrawSetSaveFinalImage(sdraw, draw->savefinalfilename));
259:   } else {
260:     PetscDraw draw;
261:     PetscCall(PetscViewerDrawGetDraw(viewer, 0, &draw));
262:   }
263:   vdraw->singleton_made = PETSC_TRUE;
264:   PetscFunctionReturn(PETSC_SUCCESS);
265: }

267: static PetscErrorCode PetscViewerRestoreSubViewer_Draw(PetscViewer viewer, MPI_Comm comm, PetscViewer *sviewer)
268: {
269:   PetscMPIInt       rank;
270:   PetscInt          i;
271:   PetscViewer_Draw *vdraw = (PetscViewer_Draw *)viewer->data, *svdraw;

273:   PetscFunctionBegin;
274:   PetscCheck(vdraw->singleton_made, PETSC_COMM_SELF, PETSC_ERR_ORDER, "Trying to restore a singleton that was not gotten");
275:   PetscCallMPI(MPI_Comm_rank(PetscObjectComm((PetscObject)viewer), &rank));
276:   if (rank == 0) {
277:     PetscDraw draw, sdraw;

279:     PetscCall(PetscViewerDrawGetDraw(viewer, 0, &draw));
280:     PetscCall(PetscViewerDrawGetDraw(*sviewer, 0, &sdraw));
281:     if (draw->savefilename) {
282:       draw->savefilecount = sdraw->savefilecount;
283:       PetscCallMPI(MPI_Bcast(&draw->savefilecount, 1, MPIU_INT, 0, PetscObjectComm((PetscObject)draw)));
284:     }
285:     svdraw = (PetscViewer_Draw *)(*sviewer)->data;
286:     for (i = 0; i < vdraw->draw_max; i++) {
287:       if (vdraw->draw[i] && svdraw->draw[i]) PetscCall(PetscDrawRestoreSingleton(vdraw->draw[i], &svdraw->draw[i]));
288:     }
289:     PetscCall(PetscFree3(svdraw->draw, svdraw->drawlg, svdraw->drawaxis));
290:     PetscCall(PetscFree((*sviewer)->data));
291:     PetscCall(PetscHeaderDestroy(sviewer));
292:   } else {
293:     PetscDraw draw;

295:     PetscCall(PetscViewerDrawGetDraw(viewer, 0, &draw));
296:     if (draw->savefilename) PetscCallMPI(MPI_Bcast(&draw->savefilecount, 1, MPIU_INT, 0, PetscObjectComm((PetscObject)draw)));
297:   }

299:   vdraw->singleton_made = PETSC_FALSE;
300:   PetscFunctionReturn(PETSC_SUCCESS);
301: }

303: static PetscErrorCode PetscViewerSetFromOptions_Draw(PetscViewer v, PetscOptionItems PetscOptionsObject)
304: {
305:   PetscReal bounds[16];
306:   PetscInt  nbounds = 16;
307:   PetscBool flg;

309:   PetscFunctionBegin;
310:   PetscOptionsHeadBegin(PetscOptionsObject, "Draw PetscViewer Options");
311:   PetscCall(PetscOptionsRealArray("-draw_bounds", "Bounds to put on plots axis", "PetscViewerDrawSetBounds", bounds, &nbounds, &flg));
312:   if (flg) PetscCall(PetscViewerDrawSetBounds(v, nbounds / 2, bounds));
313:   PetscOptionsHeadEnd();
314:   PetscFunctionReturn(PETSC_SUCCESS);
315: }

317: static PetscErrorCode PetscViewerView_Draw(PetscViewer viewer, PetscViewer v)
318: {
319:   PetscDraw         draw;
320:   PetscInt          i;
321:   PetscViewer_Draw *vdraw = (PetscViewer_Draw *)viewer->data;
322:   PetscBool         iascii;

324:   PetscFunctionBegin;
325:   PetscCall(PetscObjectTypeCompare((PetscObject)v, PETSCVIEWERASCII, &iascii));
326:   if (iascii) PetscCall(PetscViewerASCIIPrintf(v, "Draw viewer is of type %s\n", vdraw->drawtype));
327:   /*  If the PetscViewer has just been created then no vdraw->draw yet
328:       exists so this will not actually call the viewer on any draws. */
329:   for (i = 0; i < vdraw->draw_base; i++) {
330:     if (vdraw->draw[i]) {
331:       PetscCall(PetscViewerDrawGetDraw(viewer, i, &draw));
332:       PetscCall(PetscDrawView(draw, v));
333:     }
334:   }
335:   PetscFunctionReturn(PETSC_SUCCESS);
336: }

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

341:   Level: beginner

343: .seealso: [](sec_viewers), `PetscViewerDrawOpen()`, `PetscViewerDrawGetDraw()`, `PETSC_VIEWER_DRAW_()`, `PETSC_VIEWER_DRAW_SELF`, `PETSC_VIEWER_DRAW_WORLD`,
344:           `PetscViewerCreate()`, `PetscViewerASCIIOpen()`, `PetscViewerBinaryOpen()`, `PETSCVIEWERBINARY`,
345:           `PetscViewerMatlabOpen()`, `VecView()`, `DMView()`, `PetscViewerMatlabPutArray()`, `PETSCVIEWERASCII`, `PETSCVIEWERMATLAB`,
346:           `PetscViewerFileSetName()`, `PetscViewerFileSetMode()`, `PetscViewerFormat`, `PetscViewerType`, `PetscViewerSetType()`
347: M*/
348: PETSC_EXTERN PetscErrorCode PetscViewerCreate_Draw(PetscViewer viewer)
349: {
350:   PetscViewer_Draw *vdraw;

352:   PetscFunctionBegin;
353:   PetscCall(PetscNew(&vdraw));
354:   viewer->data = (void *)vdraw;

356:   viewer->ops->flush            = PetscViewerFlush_Draw;
357:   viewer->ops->view             = PetscViewerView_Draw;
358:   viewer->ops->destroy          = PetscViewerDestroy_Draw;
359:   viewer->ops->setfromoptions   = PetscViewerSetFromOptions_Draw;
360:   viewer->ops->getsubviewer     = PetscViewerGetSubViewer_Draw;
361:   viewer->ops->restoresubviewer = PetscViewerRestoreSubViewer_Draw;

363:   /* these are created on the fly if requested */
364:   vdraw->draw_max  = 5;
365:   vdraw->draw_base = 0;
366:   vdraw->w         = PETSC_DECIDE;
367:   vdraw->h         = PETSC_DECIDE;

369:   PetscCall(PetscCalloc3(vdraw->draw_max, &vdraw->draw, vdraw->draw_max, &vdraw->drawlg, vdraw->draw_max, &vdraw->drawaxis));
370:   vdraw->singleton_made = PETSC_FALSE;
371:   PetscFunctionReturn(PETSC_SUCCESS);
372: }

374: /*@
375:   PetscViewerDrawClear - Clears a `PetscDraw` graphic associated with a `PetscViewer`.

377:   Not Collective

379:   Input Parameter:
380: . viewer - the `PetscViewer`

382:   Level: intermediate

384: .seealso: [](sec_viewers), `PETSCVIEWERDRAW`, `PetscViewerDrawOpen()`, `PetscViewerDrawGetDraw()`,
385: @*/
386: PetscErrorCode PetscViewerDrawClear(PetscViewer viewer)
387: {
388:   PetscViewer_Draw *vdraw;
389:   PetscBool         isdraw;
390:   PetscInt          i;

392:   PetscFunctionBegin;
394:   PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERDRAW, &isdraw));
395:   if (!isdraw) PetscFunctionReturn(PETSC_SUCCESS);
396:   vdraw = (PetscViewer_Draw *)viewer->data;

398:   for (i = 0; i < vdraw->draw_max; i++) {
399:     if (vdraw->draw[i]) PetscCall(PetscDrawClear(vdraw->draw[i]));
400:   }
401:   PetscFunctionReturn(PETSC_SUCCESS);
402: }

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

407:   Not Collective

409:   Input Parameter:
410: . viewer - the `PetscViewer`

412:   Output Parameter:
413: . pause - the pause value

415:   Level: intermediate

417: .seealso: [](sec_viewers), `PETSCVIEWERDRAW`, `PetscViewerDrawOpen()`, `PetscViewerDrawGetDraw()`,
418: @*/
419: PetscErrorCode PetscViewerDrawGetPause(PetscViewer viewer, PetscReal *pause)
420: {
421:   PetscViewer_Draw *vdraw;
422:   PetscBool         isdraw;
423:   PetscInt          i;
424:   PetscDraw         draw;

426:   PetscFunctionBegin;
428:   PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERDRAW, &isdraw));
429:   if (!isdraw) {
430:     *pause = 0.0;
431:     PetscFunctionReturn(PETSC_SUCCESS);
432:   }
433:   vdraw = (PetscViewer_Draw *)viewer->data;

435:   for (i = 0; i < vdraw->draw_max; i++) {
436:     if (vdraw->draw[i]) {
437:       PetscCall(PetscDrawGetPause(vdraw->draw[i], pause));
438:       PetscFunctionReturn(PETSC_SUCCESS);
439:     }
440:   }
441:   /* none exist yet so create one and get its pause */
442:   PetscCall(PetscViewerDrawGetDraw(viewer, 0, &draw));
443:   PetscCall(PetscDrawGetPause(draw, pause));
444:   PetscFunctionReturn(PETSC_SUCCESS);
445: }

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

450:   Not Collective

452:   Input Parameters:
453: + viewer - the `PetscViewer`
454: - pause  - the pause value

456:   Level: intermediate

458: .seealso: [](sec_viewers), `PETSCVIEWERDRAW`, `PetscViewerDrawOpen()`, `PetscViewerDrawGetDraw()`,
459: @*/
460: PetscErrorCode PetscViewerDrawSetPause(PetscViewer viewer, PetscReal pause)
461: {
462:   PetscViewer_Draw *vdraw;
463:   PetscBool         isdraw;
464:   PetscInt          i;

466:   PetscFunctionBegin;
468:   PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERDRAW, &isdraw));
469:   if (!isdraw) PetscFunctionReturn(PETSC_SUCCESS);
470:   vdraw = (PetscViewer_Draw *)viewer->data;

472:   vdraw->pause = pause;
473:   for (i = 0; i < vdraw->draw_max; i++) {
474:     if (vdraw->draw[i]) PetscCall(PetscDrawSetPause(vdraw->draw[i], pause));
475:   }
476:   PetscFunctionReturn(PETSC_SUCCESS);
477: }

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

482:   Not Collective

484:   Input Parameters:
485: + viewer - the `PetscViewer`
486: - hold   - `PETSC_TRUE` indicates to hold the previous image

488:   Level: intermediate

490: .seealso: [](sec_viewers), `PETSCVIEWERDRAW`, `PetscViewerDrawOpen()`, `PetscViewerDrawGetDraw()`,
491: @*/
492: PetscErrorCode PetscViewerDrawSetHold(PetscViewer viewer, PetscBool hold)
493: {
494:   PetscViewer_Draw *vdraw;
495:   PetscBool         isdraw;

497:   PetscFunctionBegin;
499:   PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERDRAW, &isdraw));
500:   if (!isdraw) PetscFunctionReturn(PETSC_SUCCESS);
501:   vdraw = (PetscViewer_Draw *)viewer->data;

503:   vdraw->hold = hold;
504:   PetscFunctionReturn(PETSC_SUCCESS);
505: }

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

510:   Not Collective

512:   Input Parameter:
513: . viewer - the `PetscViewer`

515:   Output Parameter:
516: . hold - indicates to hold or not

518:   Level: intermediate

520: .seealso: [](sec_viewers), `PETSCVIEWERDRAW`, `PetscViewerDrawOpen()`, `PetscViewerDrawGetDraw()`,
521: @*/
522: PetscErrorCode PetscViewerDrawGetHold(PetscViewer viewer, PetscBool *hold)
523: {
524:   PetscViewer_Draw *vdraw;
525:   PetscBool         isdraw;

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

536:   *hold = vdraw->hold;
537:   PetscFunctionReturn(PETSC_SUCCESS);
538: }

540: /*
541:     The variable Petsc_Viewer_Draw_keyval is used to indicate an MPI attribute that
542:   is attached to a communicator, in this case the attribute is a PetscViewer.
543: */
544: PetscMPIInt Petsc_Viewer_Draw_keyval = MPI_KEYVAL_INVALID;

546: /*@C
547:    PETSC_VIEWER_DRAW_ - Creates a window `PETSCVIEWERDRAW` `PetscViewer` shared by all processors
548:                      in an MPI communicator.

550:    Collective

552:    Input Parameter:
553: .  comm - the MPI communicator to share the window `PetscViewer`

555:    Level: intermediate

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

560:    Unlike almost all other PETSc routines, `PETSC_VIEWER_DRAW_()` does not return
561:    an error code.  The window is usually used in the form
562: .vb
563:    XXXView(XXX object, PETSC_VIEWER_DRAW_(comm));
564: .ve

566: .seealso: [](sec_viewers), `PETSCVIEWERDRAW`, `PetscViewer`, `PETSC_VIEWER_DRAW_WORLD`, `PETSC_VIEWER_DRAW_SELF`, `PetscViewerDrawOpen()`,
567: @*/
568: PetscViewer PETSC_VIEWER_DRAW_(MPI_Comm comm)
569: {
570:   PetscMPIInt flag;
571:   PetscViewer viewer;
572:   MPI_Comm    ncomm;

574:   PetscFunctionBegin;
575:   PetscCallNull(PetscCommDuplicate(comm, &ncomm, NULL));
576:   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)); }
577:   PetscCallMPINull(MPI_Comm_get_attr(ncomm, Petsc_Viewer_Draw_keyval, (void **)&viewer, &flag));
578:   if (!flag) { /* PetscViewer not yet created */
579:     PetscCallNull(PetscViewerDrawOpen(ncomm, NULL, NULL, PETSC_DECIDE, PETSC_DECIDE, 300, 300, &viewer));
580:     PetscCallNull(PetscObjectRegisterDestroy((PetscObject)viewer));
581:     PetscCallMPINull(MPI_Comm_set_attr(ncomm, Petsc_Viewer_Draw_keyval, (void *)viewer));
582:   }
583:   PetscCallNull(PetscCommDestroy(&ncomm));
584:   PetscFunctionReturn(viewer);
585: }

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

590:   Collective

592:   Input Parameters:
593: + viewer  - the Petsc`Viewer` (created with `PetscViewerDrawOpen()`)
594: . nbounds - number of plots that can be made with this viewer, for example the dof passed to `DMDACreate()`
595: - 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, .....

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

600:   Level: intermediate

602:   Note:
603:   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
604:   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
605:   this viewer. Otherwise the color to physical value meaning changes with each new image if this is not set.

607: .seealso: [](sec_viewers), `PETSCVIEWERDRAW`, `PetscViewerDrawGetLG()`, `PetscViewerDrawGetAxis()`, `PetscViewerDrawOpen()`
608: @*/
609: PetscErrorCode PetscViewerDrawSetBounds(PetscViewer viewer, PetscInt nbounds, const PetscReal *bounds)
610: {
611:   PetscViewer_Draw *vdraw;
612:   PetscBool         isdraw;

614:   PetscFunctionBegin;
616:   PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERDRAW, &isdraw));
617:   if (!isdraw) PetscFunctionReturn(PETSC_SUCCESS);
618:   vdraw = (PetscViewer_Draw *)viewer->data;

620:   vdraw->nbounds = nbounds;
621:   PetscCall(PetscFree(vdraw->bounds));
622:   PetscCall(PetscMalloc1(2 * nbounds, &vdraw->bounds));
623:   PetscCall(PetscArraycpy(vdraw->bounds, bounds, 2 * nbounds));
624:   PetscFunctionReturn(PETSC_SUCCESS);
625: }

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

630:   Collective

632:   Input Parameter:
633: . viewer - the `PetscViewer` (created with `PetscViewerDrawOpen()`)

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

639:   Level: intermediate

641: .seealso: [](sec_viewers), `PETSCVIEWERDRAW`, `PetscViewerDrawGetLG()`, `PetscViewerDrawGetAxis()`, `PetscViewerDrawOpen()`, `PetscViewerDrawSetBounds()`
642: @*/
643: PetscErrorCode PetscViewerDrawGetBounds(PetscViewer viewer, PetscInt *nbounds, const PetscReal *bounds[])
644: {
645:   PetscViewer_Draw *vdraw;
646:   PetscBool         isdraw;

648:   PetscFunctionBegin;
650:   PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERDRAW, &isdraw));
651:   if (!isdraw) {
652:     if (nbounds) *nbounds = 0;
653:     if (bounds) *bounds = NULL;
654:     PetscFunctionReturn(PETSC_SUCCESS);
655:   }
656:   vdraw = (PetscViewer_Draw *)viewer->data;

658:   if (nbounds) *nbounds = vdraw->nbounds;
659:   if (bounds) *bounds = vdraw->bounds;
660:   PetscFunctionReturn(PETSC_SUCCESS);
661: }

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

666:   Collective

668:   Input Parameters:
669: + viewer - the viewer in which to display the line graphs, it not a `PETSCVIEWERDRAW` it will set to that `PetscViewerType`
670: . host   - the host to open the window on, 'NULL' indicates the local host
671: . title  - the title at the top of the window
672: . metric - the label above the graph
673: . l      - the number of curves
674: . names  - the names of each curve to be used in displaying the legend. May be 'NULL'
675: . x      - horizontal screen coordinate of the upper left corner of window, or use `PETSC_DECIDE`
676: . y      - vertical screen coordinate of the upper left corner of window, or use `PETSC_DECIDE`
677: . 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`
678: - 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`

680:   Level: developer

682: .seealso: `PetscViewer()`, `PETSCVIEWERDRAW`, `PetscViewerDrawGetDrawLG()`, `PetscViewerDrawOpen()`, `PetscViewerDrawSetInfo()`
683: @*/
684: 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
685: {
686:   PetscDrawAxis axis;
687:   PetscDrawLG   lg;

689:   PetscFunctionBegin;
690:   PetscCall(PetscViewerSetType(viewer, PETSCVIEWERDRAW));
691:   PetscCall(PetscViewerDrawSetInfo(viewer, host, title, x, y, m, n));
692:   PetscCall(PetscViewerDrawGetDrawLG(viewer, 0, &lg));
693:   if (names) PetscCall(PetscDrawLGSetLegend(lg, names));
694:   PetscCall(PetscDrawLGSetFromOptions(lg));
695:   PetscCall(PetscDrawLGGetAxis(lg, &axis));
696:   PetscCall(PetscDrawAxisSetLabels(axis, "Convergence", "Iteration", metric));
697:   PetscFunctionReturn(PETSC_SUCCESS);
698: }