Actual source code: drawv.c


  2: #include <../src/sys/classes/viewer/impls/draw/vdraw.h>
  3: #include <petscviewer.h>

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

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

 26: static PetscErrorCode PetscViewerFlush_Draw(PetscViewer v)
 27: {
 28:   PetscInt          i;
 29:   PetscViewer_Draw *vdraw = (PetscViewer_Draw *)v->data;

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

 38: /*@C
 39:     PetscViewerDrawGetDraw - Returns `PetscDraw` object from `PETSCVIEWERDRAW` `PetscViewer` object.
 40:     This `PetscDraw` object may then be used to perform graphics using `PetscDraw` commands.

 42:     Collective

 44:     Input Parameters:
 45: +   viewer - the `PetscViewer` (created with `PetscViewerDrawOpen()` of type `PETSCVIEWERDRAW`)
 46: -   windownumber - indicates which subwindow (usually 0) to obtain

 48:     Output Parameter:
 49: .   draw - the draw object

 51:     Level: intermediate

 53: .seealso: [](sec_viewers), `PETSCVIEWERDRAW`, `PetscViewerDrawGetLG()`, `PetscViewerDrawGetAxis()`, `PetscViewerDrawOpen()`
 54: @*/
 55: PetscErrorCode PetscViewerDrawGetDraw(PetscViewer viewer, PetscInt windownumber, PetscDraw *draw)
 56: {
 57:   PetscViewer_Draw *vdraw;
 58:   PetscBool         isdraw;

 60:   PetscFunctionBegin;
 64:   PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERDRAW, &isdraw));
 65:   PetscCheck(isdraw, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Must be draw type PetscViewer");
 66:   PetscCheck(windownumber >= 0, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Window number cannot be negative");
 67:   vdraw = (PetscViewer_Draw *)viewer->data;

 69:   windownumber += vdraw->draw_base;
 70:   if (windownumber >= vdraw->draw_max) {
 71:     /* allocate twice as many slots as needed */
 72:     PetscInt       draw_max = vdraw->draw_max;
 73:     PetscDraw     *tdraw    = vdraw->draw;
 74:     PetscDrawLG   *drawlg   = vdraw->drawlg;
 75:     PetscDrawAxis *drawaxis = vdraw->drawaxis;

 77:     vdraw->draw_max = 2 * windownumber;

 79:     PetscCall(PetscCalloc3(vdraw->draw_max, &vdraw->draw, vdraw->draw_max, &vdraw->drawlg, vdraw->draw_max, &vdraw->drawaxis));
 80:     PetscCall(PetscArraycpy(vdraw->draw, tdraw, draw_max));
 81:     PetscCall(PetscArraycpy(vdraw->drawlg, drawlg, draw_max));
 82:     PetscCall(PetscArraycpy(vdraw->drawaxis, drawaxis, draw_max));
 83:     PetscCall(PetscFree3(tdraw, drawlg, drawaxis));
 84:   }

 86:   if (!vdraw->draw[windownumber]) {
 87:     char *title = vdraw->title, tmp_str[128];
 88:     if (windownumber) {
 89:       PetscCall(PetscSNPrintf(tmp_str, sizeof(tmp_str), "%s:%" PetscInt_FMT, vdraw->title ? vdraw->title : "", windownumber));
 90:       title = tmp_str;
 91:     }
 92:     PetscCall(PetscDrawCreate(PetscObjectComm((PetscObject)viewer), vdraw->display, title, PETSC_DECIDE, PETSC_DECIDE, vdraw->w, vdraw->h, &vdraw->draw[windownumber]));
 93:     if (vdraw->drawtype) PetscCall(PetscDrawSetType(vdraw->draw[windownumber], vdraw->drawtype));
 94:     PetscCall(PetscDrawSetPause(vdraw->draw[windownumber], vdraw->pause));
 95:     PetscCall(PetscDrawSetOptionsPrefix(vdraw->draw[windownumber], ((PetscObject)viewer)->prefix));
 96:     PetscCall(PetscDrawSetFromOptions(vdraw->draw[windownumber]));
 97:   }
 98:   if (draw) *draw = vdraw->draw[windownumber];
100:   PetscFunctionReturn(PETSC_SUCCESS);
101: }

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

106:     Logically Collective

108:     Input Parameters:
109: +  viewer - the `PetscViewer` (created with `PetscViewerDrawOpen()`)
110: -   windownumber - how much to add to the base

112:     Level: developer

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

117: .seealso: [](sec_viewers), `PetscViewerDrawGetLG()`, `PetscViewerDrawGetAxis()`, `PetscViewerDrawOpen()`, `PetscViewerDrawGetDraw()`, `PetscViewerDrawBaseSet()`
118: @*/
119: PetscErrorCode PetscViewerDrawBaseAdd(PetscViewer viewer, PetscInt windownumber)
120: {
121:   PetscViewer_Draw *vdraw;
122:   PetscBool         isdraw;

124:   PetscFunctionBegin;
127:   PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERDRAW, &isdraw));
128:   PetscCheck(isdraw, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Must be draw type PetscViewer");
129:   vdraw = (PetscViewer_Draw *)viewer->data;

131:   PetscCheck(windownumber + vdraw->draw_base >= 0, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Resulting base %" PetscInt_FMT " cannot be negative", windownumber + vdraw->draw_base);
132:   vdraw->draw_base += windownumber;
133:   PetscFunctionReturn(PETSC_SUCCESS);
134: }

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

139:     Logically Collective

141:     Input Parameters:
142: +   viewer - the `PetscViewer` (created with `PetscViewerDrawOpen()`)
143: -   windownumber - value to set the base

145:     Level: developer

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

150: .seealso: [](sec_viewers), `PetscViewerDrawGetLG()`, `PetscViewerDrawGetAxis()`, `PetscViewerDrawOpen()`, `PetscViewerDrawGetDraw()`, `PetscViewerDrawBaseAdd()`
151: @*/
152: PetscErrorCode PetscViewerDrawBaseSet(PetscViewer viewer, PetscInt windownumber)
153: {
154:   PetscViewer_Draw *vdraw;
155:   PetscBool         isdraw;

157:   PetscFunctionBegin;
160:   PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERDRAW, &isdraw));
161:   PetscCheck(isdraw, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Must be draw type PetscViewer");
162:   vdraw = (PetscViewer_Draw *)viewer->data;

164:   PetscCheck(windownumber >= 0, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Resulting base %" PetscInt_FMT " cannot be negative", windownumber);
165:   vdraw->draw_base = windownumber;
166:   PetscFunctionReturn(PETSC_SUCCESS);
167: }

169: /*@C
170:     PetscViewerDrawGetDrawLG - Returns a `PetscDrawLG` object from `PetscViewer` object of type `PETSCVIEWERDRAW`.
171:     This `PetscDrawLG` object may then be used to perform graphics using `PetscDrawLG` commands.

173:     Collective

175:     Input Parameters:
176: +   viewer - the `PetscViewer` (created with `PetscViewerDrawOpen()`)
177: -   windownumber - indicates which subwindow (usually 0)

179:     Output Parameter:
180: .   draw - the draw line graph object

182:     Level: intermediate

184:     Note:
185:     A `PETSCVIEWERDRAW` may have multiple `PetscDraw` subwindows

187: .seealso: [](sec_viewers), `PetscDrawLG`, `PetscViewerDrawGetDraw()`, `PetscViewerDrawGetAxis()`, `PetscViewerDrawOpen()`
188: @*/
189: PetscErrorCode PetscViewerDrawGetDrawLG(PetscViewer viewer, PetscInt windownumber, PetscDrawLG *drawlg)
190: {
191:   PetscBool         isdraw;
192:   PetscViewer_Draw *vdraw;

194:   PetscFunctionBegin;
198:   PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERDRAW, &isdraw));
199:   PetscCheck(isdraw, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Must be draw type PetscViewer");
200:   PetscCheck(windownumber >= 0, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Window number cannot be negative");
201:   vdraw = (PetscViewer_Draw *)viewer->data;

203:   if (windownumber + vdraw->draw_base >= vdraw->draw_max || !vdraw->draw[windownumber + vdraw->draw_base]) PetscCall(PetscViewerDrawGetDraw(viewer, windownumber, NULL));
204:   if (!vdraw->drawlg[windownumber + vdraw->draw_base]) {
205:     PetscCall(PetscDrawLGCreate(vdraw->draw[windownumber + vdraw->draw_base], 1, &vdraw->drawlg[windownumber + vdraw->draw_base]));
206:     PetscCall(PetscDrawLGSetFromOptions(vdraw->drawlg[windownumber + vdraw->draw_base]));
207:   }
208:   *drawlg = vdraw->drawlg[windownumber + vdraw->draw_base];
209:   PetscFunctionReturn(PETSC_SUCCESS);
210: }

212: /*@C
213:     PetscViewerDrawGetDrawAxis - Returns a `PetscDrawAxis` object from a `PetscViewer` object of type `PETSCVIEWERDRAW`.
214:     This `PetscDrawAxis` object may then be used to perform graphics using `PetscDrawAxis` commands.

216:     Collective

218:     Input Parameters:
219: +   viewer - the `PetscViewer` (created with `PetscViewerDrawOpen()`)
220: -   windownumber - indicates which subwindow (usually 0)

222:     Output Parameter:
223: .   drawaxis - the draw axis object

225:     Level: advanced

227:     Note:
228:     A `PETSCVIEWERDRAW` may have multiple `PetscDraw` subwindows

230: .seealso: [](sec_viewers), `PetscViewerDrawGetDraw()`, `PetscViewerDrawGetLG()`, `PetscViewerDrawOpen()`
231: @*/
232: PetscErrorCode PetscViewerDrawGetDrawAxis(PetscViewer viewer, PetscInt windownumber, PetscDrawAxis *drawaxis)
233: {
234:   PetscBool         isdraw;
235:   PetscViewer_Draw *vdraw;

237:   PetscFunctionBegin;
241:   PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERDRAW, &isdraw));
242:   PetscCheck(isdraw, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Must be draw type PetscViewer");
243:   PetscCheck(windownumber >= 0, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Window number cannot be negative");
244:   vdraw = (PetscViewer_Draw *)viewer->data;

246:   if (windownumber + vdraw->draw_base >= vdraw->draw_max || !vdraw->draw[windownumber + vdraw->draw_base]) PetscCall(PetscViewerDrawGetDraw(viewer, windownumber, NULL));
247:   if (!vdraw->drawaxis[windownumber + vdraw->draw_base]) PetscCall(PetscDrawAxisCreate(vdraw->draw[windownumber + vdraw->draw_base], &vdraw->drawaxis[windownumber + vdraw->draw_base]));
248:   *drawaxis = vdraw->drawaxis[windownumber + vdraw->draw_base];
249:   PetscFunctionReturn(PETSC_SUCCESS);
250: }

252: PetscErrorCode PetscViewerDrawResize(PetscViewer v, int w, int h)
253: {
254:   PetscViewer_Draw *vdraw;
255:   PetscBool         isdraw;

257:   PetscFunctionBegin;
259:   PetscCall(PetscObjectTypeCompare((PetscObject)v, PETSCVIEWERDRAW, &isdraw));
260:   if (!isdraw) PetscFunctionReturn(PETSC_SUCCESS);
261:   vdraw = (PetscViewer_Draw *)v->data;

263:   if (w >= 1) vdraw->w = w;
264:   if (h >= 1) vdraw->h = h;
265:   PetscFunctionReturn(PETSC_SUCCESS);
266: }

268: PetscErrorCode PetscViewerDrawSetInfo(PetscViewer v, const char display[], const char title[], int x, int y, int w, int h)
269: {
270:   PetscViewer_Draw *vdraw;
271:   PetscBool         isdraw;

273:   PetscFunctionBegin;
275:   PetscCall(PetscObjectTypeCompare((PetscObject)v, PETSCVIEWERDRAW, &isdraw));
276:   if (!isdraw) PetscFunctionReturn(PETSC_SUCCESS);
277:   vdraw = (PetscViewer_Draw *)v->data;

279:   PetscCall(PetscStrallocpy(display, &vdraw->display));
280:   PetscCall(PetscStrallocpy(title, &vdraw->title));
281:   if (w >= 1) vdraw->w = w;
282:   if (h >= 1) vdraw->h = h;
283:   PetscFunctionReturn(PETSC_SUCCESS);
284: }

286: PetscErrorCode PetscViewerDrawSetDrawType(PetscViewer v, PetscDrawType drawtype)
287: {
288:   PetscViewer_Draw *vdraw;
289:   PetscBool         isdraw;

291:   PetscFunctionBegin;
293:   PetscCall(PetscObjectTypeCompare((PetscObject)v, PETSCVIEWERDRAW, &isdraw));
294:   if (!isdraw) PetscFunctionReturn(PETSC_SUCCESS);
295:   vdraw = (PetscViewer_Draw *)v->data;

297:   PetscCall(PetscFree(vdraw->drawtype));
298:   PetscCall(PetscStrallocpy(drawtype, (char **)&vdraw->drawtype));
299:   PetscFunctionReturn(PETSC_SUCCESS);
300: }

302: PetscErrorCode PetscViewerDrawGetDrawType(PetscViewer v, PetscDrawType *drawtype)
303: {
304:   PetscViewer_Draw *vdraw;
305:   PetscBool         isdraw;

307:   PetscFunctionBegin;
309:   PetscCall(PetscObjectTypeCompare((PetscObject)v, PETSCVIEWERDRAW, &isdraw));
310:   PetscCheck(isdraw, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Must be draw type PetscViewer");
311:   vdraw = (PetscViewer_Draw *)v->data;

313:   *drawtype = vdraw->drawtype;
314:   PetscFunctionReturn(PETSC_SUCCESS);
315: }

317: PetscErrorCode PetscViewerDrawSetTitle(PetscViewer v, const char title[])
318: {
319:   PetscViewer_Draw *vdraw;
320:   PetscBool         isdraw;

322:   PetscFunctionBegin;
324:   PetscCall(PetscObjectTypeCompare((PetscObject)v, PETSCVIEWERDRAW, &isdraw));
325:   if (!isdraw) PetscFunctionReturn(PETSC_SUCCESS);
326:   vdraw = (PetscViewer_Draw *)v->data;

328:   PetscCall(PetscFree(vdraw->title));
329:   PetscCall(PetscStrallocpy(title, &vdraw->title));
330:   PetscFunctionReturn(PETSC_SUCCESS);
331: }

333: PetscErrorCode PetscViewerDrawGetTitle(PetscViewer v, const char *title[])
334: {
335:   PetscViewer_Draw *vdraw;
336:   PetscBool         isdraw;

338:   PetscFunctionBegin;
340:   PetscCall(PetscObjectTypeCompare((PetscObject)v, PETSCVIEWERDRAW, &isdraw));
341:   PetscCheck(isdraw, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Must be draw type PetscViewer");
342:   vdraw = (PetscViewer_Draw *)v->data;

344:   *title = vdraw->title;
345:   PetscFunctionReturn(PETSC_SUCCESS);
346: }

348: /*@C
349:    PetscViewerDrawOpen - Opens a `PetscDraw` window for use as a `PetscViewer` with type `PETSCVIEWERDRAW`. If you want to
350:    do graphics in this window, you must call `PetscViewerDrawGetDraw()` and
351:    perform the graphics on the `PetscDraw` object.

353:    Collective

355:    Input Parameters:
356: +  comm - communicator that will share window
357: .  display - the X display on which to open, or `NULL` for the local machine
358: .  title - the title to put in the title bar, or `NULL` for no title
359: .  x - horizontal screen coordinate of the upper left corner of window, or use `PETSC_DECIDE`
360: .  y - vertical screen coordinate of the upper left corner of window, or use `PETSC_DECIDE`
361: .  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`
362: -  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`

364:    Output Parameter:
365: . viewer - the `PetscViewer`

367:    Format Options:
368: +  `PETSC_VIEWER_DRAW_BASIC` - displays with basic format
369: -  `PETSC_VIEWER_DRAW_LG`    - displays using a line graph

371:    Options Database Keys:
372: +  -draw_type - use x or null
373: .  -nox - Disables all x-windows output
374: .  -display <name> - Specifies name of machine for the X display
375: .  -geometry <x,y,w,h> - allows setting the window location and size
376: -  -draw_pause <pause> - Sets time (in seconds) that the
377:      program pauses after PetscDrawPause() has been called
378:      (0 is default, -1 implies until user input).

380:    Level: beginner

382:    Fortran Note:
383:    Whenever indicating null character data in a Fortran code,
384:    `PETSC_NULL_CHARACTER` must be employed; using NULL is not
385:    correct for character data!  Thus, `PETSC_NULL_CHARACTER` can be
386:    used for the display and title input parameters.

388: .seealso: [](sec_viewers), `PETSCVIEWERDRAW`, `PetscDrawCreate()`, `PetscViewerDestroy()`, `PetscViewerDrawGetDraw()`, `PetscViewerCreate()`, `PETSC_VIEWER_DRAW_`,
389:           `PETSC_VIEWER_DRAW_WORLD`, `PETSC_VIEWER_DRAW_SELF`
390: @*/
391: PetscErrorCode PetscViewerDrawOpen(MPI_Comm comm, const char display[], const char title[], int x, int y, int w, int h, PetscViewer *viewer)
392: {
393:   PetscFunctionBegin;
394:   PetscCall(PetscViewerCreate(comm, viewer));
395:   PetscCall(PetscViewerSetType(*viewer, PETSCVIEWERDRAW));
396:   PetscCall(PetscViewerDrawSetInfo(*viewer, display, title, x, y, w, h));
397:   PetscFunctionReturn(PETSC_SUCCESS);
398: }

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

402: PetscErrorCode PetscViewerGetSubViewer_Draw(PetscViewer viewer, MPI_Comm comm, PetscViewer *sviewer)
403: {
404:   PetscMPIInt       rank;
405:   PetscInt          i;
406:   PetscViewer_Draw *vdraw = (PetscViewer_Draw *)viewer->data, *svdraw;

408:   PetscFunctionBegin;
409:   PetscCheck(!vdraw->singleton_made, PETSC_COMM_SELF, PETSC_ERR_ORDER, "Trying to get SubViewer without first restoring previous");
410:   /* only processor zero can use the PetscViewer draw singleton */
411:   if (sviewer) *sviewer = NULL;
412:   PetscCallMPI(MPI_Comm_rank(PetscObjectComm((PetscObject)viewer), &rank));
413:   if (rank == 0) {
414:     PetscMPIInt flg;
415:     PetscDraw   draw, sdraw;

417:     PetscCallMPI(MPI_Comm_compare(PETSC_COMM_SELF, comm, &flg));
418:     PetscCheck(flg == MPI_IDENT || flg == MPI_CONGRUENT, PETSC_COMM_SELF, PETSC_ERR_SUP, "PetscViewerGetSubViewer() for PETSCVIEWERDRAW requires a singleton MPI_Comm");
419:     PetscCall(PetscViewerCreate(comm, sviewer));
420:     PetscCall(PetscViewerSetType(*sviewer, PETSCVIEWERDRAW));
421:     svdraw             = (PetscViewer_Draw *)(*sviewer)->data;
422:     (*sviewer)->format = viewer->format;
423:     for (i = 0; i < vdraw->draw_max; i++) { /* XXX this is wrong if svdraw->draw_max (initially 5) < vdraw->draw_max */
424:       if (vdraw->draw[i]) PetscCall(PetscDrawGetSingleton(vdraw->draw[i], &svdraw->draw[i]));
425:     }
426:     PetscCall(PetscViewerDrawGetDraw(viewer, 0, &draw));
427:     PetscCall(PetscViewerDrawGetDraw(*sviewer, 0, &sdraw));
428:     if (draw->savefilename) {
429:       PetscCall(PetscDrawSetSave(sdraw, draw->savefilename));
430:       sdraw->savefilecount  = draw->savefilecount;
431:       sdraw->savesinglefile = draw->savesinglefile;
432:       sdraw->savemoviefps   = draw->savemoviefps;
433:       sdraw->saveonclear    = draw->saveonclear;
434:       sdraw->saveonflush    = draw->saveonflush;
435:     }
436:     if (draw->savefinalfilename) PetscCall(PetscDrawSetSaveFinalImage(sdraw, draw->savefinalfilename));
437:   } else {
438:     PetscDraw draw;
439:     PetscCall(PetscViewerDrawGetDraw(viewer, 0, &draw));
440:   }
441:   vdraw->singleton_made = PETSC_TRUE;
442:   PetscFunctionReturn(PETSC_SUCCESS);
443: }

445: PetscErrorCode PetscViewerRestoreSubViewer_Draw(PetscViewer viewer, MPI_Comm comm, PetscViewer *sviewer)
446: {
447:   PetscMPIInt       rank;
448:   PetscInt          i;
449:   PetscViewer_Draw *vdraw = (PetscViewer_Draw *)viewer->data, *svdraw;

451:   PetscFunctionBegin;
452:   PetscCheck(vdraw->singleton_made, PETSC_COMM_SELF, PETSC_ERR_ORDER, "Trying to restore a singleton that was not gotten");
453:   PetscCallMPI(MPI_Comm_rank(PetscObjectComm((PetscObject)viewer), &rank));
454:   if (rank == 0) {
455:     PetscDraw draw, sdraw;

457:     PetscCall(PetscViewerDrawGetDraw(viewer, 0, &draw));
458:     PetscCall(PetscViewerDrawGetDraw(*sviewer, 0, &sdraw));
459:     if (draw->savefilename) {
460:       draw->savefilecount = sdraw->savefilecount;
461:       PetscCallMPI(MPI_Bcast(&draw->savefilecount, 1, MPIU_INT, 0, PetscObjectComm((PetscObject)draw)));
462:     }
463:     svdraw = (PetscViewer_Draw *)(*sviewer)->data;
464:     for (i = 0; i < vdraw->draw_max; i++) {
465:       if (vdraw->draw[i] && svdraw->draw[i]) PetscCall(PetscDrawRestoreSingleton(vdraw->draw[i], &svdraw->draw[i]));
466:     }
467:     PetscCall(PetscFree3(svdraw->draw, svdraw->drawlg, svdraw->drawaxis));
468:     PetscCall(PetscFree((*sviewer)->data));
469:     PetscCall(PetscHeaderDestroy(sviewer));
470:   } else {
471:     PetscDraw draw;

473:     PetscCall(PetscViewerDrawGetDraw(viewer, 0, &draw));
474:     if (draw->savefilename) PetscCallMPI(MPI_Bcast(&draw->savefilecount, 1, MPIU_INT, 0, PetscObjectComm((PetscObject)draw)));
475:   }

477:   vdraw->singleton_made = PETSC_FALSE;
478:   PetscFunctionReturn(PETSC_SUCCESS);
479: }

481: PetscErrorCode PetscViewerSetFromOptions_Draw(PetscViewer v, PetscOptionItems *PetscOptionsObject)
482: {
483:   PetscReal bounds[16];
484:   PetscInt  nbounds = 16;
485:   PetscBool flg;

487:   PetscFunctionBegin;
488:   PetscOptionsHeadBegin(PetscOptionsObject, "Draw PetscViewer Options");
489:   PetscCall(PetscOptionsRealArray("-draw_bounds", "Bounds to put on plots axis", "PetscViewerDrawSetBounds", bounds, &nbounds, &flg));
490:   if (flg) PetscCall(PetscViewerDrawSetBounds(v, nbounds / 2, bounds));
491:   PetscOptionsHeadEnd();
492:   PetscFunctionReturn(PETSC_SUCCESS);
493: }

495: PetscErrorCode PetscViewerView_Draw(PetscViewer viewer, PetscViewer v)
496: {
497:   PetscDraw         draw;
498:   PetscInt          i;
499:   PetscViewer_Draw *vdraw = (PetscViewer_Draw *)viewer->data;
500:   PetscBool         iascii;

502:   PetscFunctionBegin;
503:   PetscCall(PetscObjectTypeCompare((PetscObject)v, PETSCVIEWERASCII, &iascii));
504:   if (iascii) PetscCall(PetscViewerASCIIPrintf(v, "Draw viewer is of type %s\n", vdraw->drawtype));
505:   /*  If the PetscViewer has just been created then no vdraw->draw yet
506:       exists so this will not actually call the viewer on any draws. */
507:   for (i = 0; i < vdraw->draw_base; i++) {
508:     if (vdraw->draw[i]) {
509:       PetscCall(PetscViewerDrawGetDraw(viewer, i, &draw));
510:       PetscCall(PetscDrawView(draw, v));
511:     }
512:   }
513:   PetscFunctionReturn(PETSC_SUCCESS);
514: }

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

519:   Level: beginner

521: .seealso: [](sec_viewers), `PetscViewerDrawOpen()`, `PetscViewerDrawGetDraw()`, `PETSC_VIEWER_DRAW_()`, `PETSC_VIEWER_DRAW_SELF`, `PETSC_VIEWER_DRAW_WORLD`,
522:           `PetscViewerCreate()`, `PetscViewerASCIIOpen()`, `PetscViewerBinaryOpen()`, `PETSCVIEWERBINARY`,
523:           `PetscViewerMatlabOpen()`, `VecView()`, `DMView()`, `PetscViewerMatlabPutArray()`, `PETSCVIEWERASCII`, `PETSCVIEWERMATLAB`,
524:           `PetscViewerFileSetName()`, `PetscViewerFileSetMode()`, `PetscViewerFormat`, `PetscViewerType`, `PetscViewerSetType()`
525: M*/
526: PETSC_EXTERN PetscErrorCode PetscViewerCreate_Draw(PetscViewer viewer)
527: {
528:   PetscViewer_Draw *vdraw;

530:   PetscFunctionBegin;
531:   PetscCall(PetscNew(&vdraw));
532:   viewer->data = (void *)vdraw;

534:   viewer->ops->flush            = PetscViewerFlush_Draw;
535:   viewer->ops->view             = PetscViewerView_Draw;
536:   viewer->ops->destroy          = PetscViewerDestroy_Draw;
537:   viewer->ops->setfromoptions   = PetscViewerSetFromOptions_Draw;
538:   viewer->ops->getsubviewer     = PetscViewerGetSubViewer_Draw;
539:   viewer->ops->restoresubviewer = PetscViewerRestoreSubViewer_Draw;

541:   /* these are created on the fly if requested */
542:   vdraw->draw_max  = 5;
543:   vdraw->draw_base = 0;
544:   vdraw->w         = PETSC_DECIDE;
545:   vdraw->h         = PETSC_DECIDE;

547:   PetscCall(PetscCalloc3(vdraw->draw_max, &vdraw->draw, vdraw->draw_max, &vdraw->drawlg, vdraw->draw_max, &vdraw->drawaxis));
548:   vdraw->singleton_made = PETSC_FALSE;
549:   PetscFunctionReturn(PETSC_SUCCESS);
550: }

552: /*@
553:     PetscViewerDrawClear - Clears a `PetscDraw` graphic associated with a `PetscViewer`.

555:     Not Collective

557:     Input Parameter:
558: .  viewer - the `PetscViewer`

560:     Level: intermediate

562: .seealso: [](sec_viewers), `PETSCVIEWERDRAW`, `PetscViewerDrawOpen()`, `PetscViewerDrawGetDraw()`,
563: @*/
564: PetscErrorCode PetscViewerDrawClear(PetscViewer viewer)
565: {
566:   PetscViewer_Draw *vdraw;
567:   PetscBool         isdraw;
568:   PetscInt          i;

570:   PetscFunctionBegin;
572:   PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERDRAW, &isdraw));
573:   if (!isdraw) PetscFunctionReturn(PETSC_SUCCESS);
574:   vdraw = (PetscViewer_Draw *)viewer->data;

576:   for (i = 0; i < vdraw->draw_max; i++) {
577:     if (vdraw->draw[i]) PetscCall(PetscDrawClear(vdraw->draw[i]));
578:   }
579:   PetscFunctionReturn(PETSC_SUCCESS);
580: }

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

585:     Not Collective

587:     Input Parameter:
588: .  viewer - the `PetscViewer`

590:     Output Parameter:
591: .  pause - the pause value

593:     Level: intermediate

595: .seealso: [](sec_viewers), `PETSCVIEWERDRAW`, `PetscViewerDrawOpen()`, `PetscViewerDrawGetDraw()`,
596: @*/
597: PetscErrorCode PetscViewerDrawGetPause(PetscViewer viewer, PetscReal *pause)
598: {
599:   PetscViewer_Draw *vdraw;
600:   PetscBool         isdraw;
601:   PetscInt          i;
602:   PetscDraw         draw;

604:   PetscFunctionBegin;
606:   PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERDRAW, &isdraw));
607:   if (!isdraw) {
608:     *pause = 0.0;
609:     PetscFunctionReturn(PETSC_SUCCESS);
610:   }
611:   vdraw = (PetscViewer_Draw *)viewer->data;

613:   for (i = 0; i < vdraw->draw_max; i++) {
614:     if (vdraw->draw[i]) {
615:       PetscCall(PetscDrawGetPause(vdraw->draw[i], pause));
616:       PetscFunctionReturn(PETSC_SUCCESS);
617:     }
618:   }
619:   /* none exist yet so create one and get its pause */
620:   PetscCall(PetscViewerDrawGetDraw(viewer, 0, &draw));
621:   PetscCall(PetscDrawGetPause(draw, pause));
622:   PetscFunctionReturn(PETSC_SUCCESS);
623: }

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

628:     Not Collective

630:     Input Parameters:
631: +  viewer - the `PetscViewer`
632: -  pause - the pause value

634:     Level: intermediate

636: .seealso: [](sec_viewers), `PETSCVIEWERDRAW`, `PetscViewerDrawOpen()`, `PetscViewerDrawGetDraw()`,
637: @*/
638: PetscErrorCode PetscViewerDrawSetPause(PetscViewer viewer, PetscReal pause)
639: {
640:   PetscViewer_Draw *vdraw;
641:   PetscBool         isdraw;
642:   PetscInt          i;

644:   PetscFunctionBegin;
646:   PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERDRAW, &isdraw));
647:   if (!isdraw) PetscFunctionReturn(PETSC_SUCCESS);
648:   vdraw = (PetscViewer_Draw *)viewer->data;

650:   vdraw->pause = pause;
651:   for (i = 0; i < vdraw->draw_max; i++) {
652:     if (vdraw->draw[i]) PetscCall(PetscDrawSetPause(vdraw->draw[i], pause));
653:   }
654:   PetscFunctionReturn(PETSC_SUCCESS);
655: }

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

660:     Not Collective

662:     Input Parameters:
663: +  viewer - the `PetscViewer`
664: -  hold - `PETSC_TRUE` indicates to hold the previous image

666:     Level: intermediate

668: .seealso: [](sec_viewers), `PETSCVIEWERDRAW`, `PetscViewerDrawOpen()`, `PetscViewerDrawGetDraw()`,
669: @*/
670: PetscErrorCode PetscViewerDrawSetHold(PetscViewer viewer, PetscBool hold)
671: {
672:   PetscViewer_Draw *vdraw;
673:   PetscBool         isdraw;

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

681:   vdraw->hold = hold;
682:   PetscFunctionReturn(PETSC_SUCCESS);
683: }

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

688:     Not Collective

690:     Input Parameter:
691: .  viewer - the `PetscViewer`

693:     Output Parameter:
694: .  hold - indicates to hold or not

696:     Level: intermediate

698: .seealso: [](sec_viewers), `PETSCVIEWERDRAW`, `PetscViewerDrawOpen()`, `PetscViewerDrawGetDraw()`,
699: @*/
700: PetscErrorCode PetscViewerDrawGetHold(PetscViewer viewer, PetscBool *hold)
701: {
702:   PetscViewer_Draw *vdraw;
703:   PetscBool         isdraw;

705:   PetscFunctionBegin;
707:   PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERDRAW, &isdraw));
708:   if (!isdraw) {
709:     *hold = PETSC_FALSE;
710:     PetscFunctionReturn(PETSC_SUCCESS);
711:   }
712:   vdraw = (PetscViewer_Draw *)viewer->data;

714:   *hold = vdraw->hold;
715:   PetscFunctionReturn(PETSC_SUCCESS);
716: }

718: /*
719:     The variable Petsc_Viewer_Draw_keyval is used to indicate an MPI attribute that
720:   is attached to a communicator, in this case the attribute is a PetscViewer.
721: */
722: PetscMPIInt Petsc_Viewer_Draw_keyval = MPI_KEYVAL_INVALID;

724: /*@C
725:     PETSC_VIEWER_DRAW_ - Creates a window `PETSCVIEWERDRAW` `PetscViewer` shared by all processors
726:                      in an MPI communicator.

728:      Collective

730:      Input Parameter:
731: .    comm - the MPI communicator to share the window `PetscViewer`

733:      Level: intermediate

735:      Note:
736:      Unlike almost all other PETSc routines, `PETSC_VIEWER_DRAW_()` does not return
737:      an error code.  The window is usually used in the form
738: $       XXXView(XXX object, PETSC_VIEWER_DRAW_(comm));

740: .seealso: [](sec_viewers), `PETSCVIEWERDRAW`, `PetscViewer`, `PETSC_VIEWER_DRAW_WORLD`, `PETSC_VIEWER_DRAW_SELF`, `PetscViewerDrawOpen()`,
741: @*/
742: PetscViewer PETSC_VIEWER_DRAW_(MPI_Comm comm)
743: {
744:   PetscErrorCode ierr;
745:   PetscMPIInt    flag, mpi_ierr;
746:   PetscViewer    viewer;
747:   MPI_Comm       ncomm;

749:   PetscFunctionBegin;
750:   ierr = PetscCommDuplicate(comm, &ncomm, NULL);
751:   if (ierr) {
752:     ierr = PetscError(PETSC_COMM_SELF, __LINE__, "PETSC_VIEWER_DRAW_", __FILE__, PETSC_ERR_PLIB, PETSC_ERROR_INITIAL, " ");
753:     PetscFunctionReturn(NULL);
754:   }
755:   if (Petsc_Viewer_Draw_keyval == MPI_KEYVAL_INVALID) {
756:     mpi_ierr = MPI_Comm_create_keyval(MPI_COMM_NULL_COPY_FN, MPI_COMM_NULL_DELETE_FN, &Petsc_Viewer_Draw_keyval, NULL);
757:     if (mpi_ierr) {
758:       ierr = PetscError(PETSC_COMM_SELF, __LINE__, "PETSC_VIEWER_DRAW_", __FILE__, PETSC_ERR_PLIB, PETSC_ERROR_INITIAL, " ");
759:       PetscFunctionReturn(NULL);
760:     }
761:   }
762:   mpi_ierr = MPI_Comm_get_attr(ncomm, Petsc_Viewer_Draw_keyval, (void **)&viewer, &flag);
763:   if (mpi_ierr) {
764:     ierr = PetscError(PETSC_COMM_SELF, __LINE__, "PETSC_VIEWER_DRAW_", __FILE__, PETSC_ERR_PLIB, PETSC_ERROR_INITIAL, " ");
765:     PetscFunctionReturn(NULL);
766:   }
767:   if (!flag) { /* PetscViewer not yet created */
768:     ierr = PetscViewerDrawOpen(ncomm, NULL, NULL, PETSC_DECIDE, PETSC_DECIDE, 300, 300, &viewer);
769:     if (ierr) {
770:       ierr = PetscError(PETSC_COMM_SELF, __LINE__, "PETSC_VIEWER_DRAW_", __FILE__, PETSC_ERR_PLIB, PETSC_ERROR_REPEAT, " ");
771:       PetscFunctionReturn(NULL);
772:     }
773:     ierr = PetscObjectRegisterDestroy((PetscObject)viewer);
774:     if (ierr) {
775:       ierr = PetscError(PETSC_COMM_SELF, __LINE__, "PETSC_VIEWER_DRAW_", __FILE__, PETSC_ERR_PLIB, PETSC_ERROR_REPEAT, " ");
776:       PetscFunctionReturn(NULL);
777:     }
778:     mpi_ierr = MPI_Comm_set_attr(ncomm, Petsc_Viewer_Draw_keyval, (void *)viewer);
779:     if (mpi_ierr) {
780:       ierr = PetscError(PETSC_COMM_SELF, __LINE__, "PETSC_VIEWER_DRAW_", __FILE__, PETSC_ERR_PLIB, PETSC_ERROR_INITIAL, " ");
781:       PetscFunctionReturn(NULL);
782:     }
783:   }
784:   ierr = PetscCommDestroy(&ncomm);
785:   if (ierr) {
786:     ierr = PetscError(PETSC_COMM_SELF, __LINE__, "PETSC_VIEWER_DRAW_", __FILE__, PETSC_ERR_PLIB, PETSC_ERROR_REPEAT, " ");
787:     PetscFunctionReturn(NULL);
788:   }
789:   PetscFunctionReturn(viewer);
790: }

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

795:     Collective

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

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

805:     Level: intermediate

807:     Note:
808:     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
809:       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
810:       this viewer. Otherwise the color to physical value meaning changes with each new image if this is not set.

812: .seealso: [](sec_viewers), `PETSCVIEWERDRAW`, `PetscViewerDrawGetLG()`, `PetscViewerDrawGetAxis()`, `PetscViewerDrawOpen()`
813: @*/
814: PetscErrorCode PetscViewerDrawSetBounds(PetscViewer viewer, PetscInt nbounds, const PetscReal *bounds)
815: {
816:   PetscViewer_Draw *vdraw;
817:   PetscBool         isdraw;

819:   PetscFunctionBegin;
821:   PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERDRAW, &isdraw));
822:   if (!isdraw) PetscFunctionReturn(PETSC_SUCCESS);
823:   vdraw = (PetscViewer_Draw *)viewer->data;

825:   vdraw->nbounds = nbounds;
826:   PetscCall(PetscFree(vdraw->bounds));
827:   PetscCall(PetscMalloc1(2 * nbounds, &vdraw->bounds));
828:   PetscCall(PetscArraycpy(vdraw->bounds, bounds, 2 * nbounds));
829:   PetscFunctionReturn(PETSC_SUCCESS);
830: }

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

835:     Collective

837:     Input Parameter:
838: .   viewer - the `PetscViewer` (created with `PetscViewerDrawOpen()`)

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

844:     Level: intermediate

846: .seealso: [](sec_viewers), `PETSCVIEWERDRAW`, `PetscViewerDrawGetLG()`, `PetscViewerDrawGetAxis()`, `PetscViewerDrawOpen()`, `PetscViewerDrawSetBounds()`
847: @*/
848: PetscErrorCode PetscViewerDrawGetBounds(PetscViewer viewer, PetscInt *nbounds, const PetscReal **bounds)
849: {
850:   PetscViewer_Draw *vdraw;
851:   PetscBool         isdraw;

853:   PetscFunctionBegin;
855:   PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERDRAW, &isdraw));
856:   if (!isdraw) {
857:     if (nbounds) *nbounds = 0;
858:     if (bounds) *bounds = NULL;
859:     PetscFunctionReturn(PETSC_SUCCESS);
860:   }
861:   vdraw = (PetscViewer_Draw *)viewer->data;

863:   if (nbounds) *nbounds = vdraw->nbounds;
864:   if (bounds) *bounds = vdraw->bounds;
865:   PetscFunctionReturn(PETSC_SUCCESS);
866: }