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 `PetscViewer` object.
 40:     This `PetscDraw` object may then be used to perform graphics using
 41:     `PetscDraw` commands.

 43:     Collective

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

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

 52:     Level: intermediate

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

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

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

 78:     vdraw->draw_max = 2 * windownumber;

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

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

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

107:     Logically Collective

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

113:     Level: developer

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

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

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

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

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

140:     Logically Collective

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

146:     Level: developer

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

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

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

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

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

174:     Collective

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

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

183:     Level: intermediate

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

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

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

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

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

217:     Collective

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

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

226:     Level: advanced

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

354:    Collective

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

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

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

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

381:    Level: beginner

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

520:   Level: beginner

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

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

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

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

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

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

556:     Not Collective

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

561:     Level: intermediate

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

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

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

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

586:     Not Collective

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

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

594:     Level: intermediate

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

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

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

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

629:     Not Collective

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

635:     Level: intermediate

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

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

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

658: /*@
659:     PetscViewerDrawSetHold - Holds previous image when drawing new image

661:     Not Collective

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

667:     Level: intermediate

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

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

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

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

689:     Not Collective

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

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

697:     Level: intermediate

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

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

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

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

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

729:      Collective

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

734:      Level: intermediate

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

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

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

793: /*@
794:     PetscViewerDrawSetBounds - sets the upper and lower bounds to be used in plotting

796:     Collective

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

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

806:     Level: intermediate

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

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

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

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

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

836:     Collective

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

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

845:     Level: intermediate

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

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

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