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: /*@C
 38:   PetscViewerDrawGetDraw - Returns `PetscDraw` object from `PETSCVIEWERDRAW` `PetscViewer` object.
 39:   This `PetscDraw` object may then be used to perform graphics using `PetscDraw` commands.

 41:   Collective

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

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

 50:   Level: intermediate

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

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

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

 76:     vdraw->draw_max = 2 * windownumber;

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

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

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

105:   Logically Collective

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

111:   Level: developer

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

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

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

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

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

138:   Logically Collective

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

144:   Level: developer

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

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

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

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

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

172:   Collective

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

178:   Output Parameter:
179: . drawlg - the draw line graph object

181:   Level: intermediate

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

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

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

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

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

215:   Collective

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

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

224:   Level: advanced

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

347: /*@C
348:   PetscViewerDrawOpen - Opens a `PetscDraw` window for use as a `PetscViewer` with type
349:   `PETSCVIEWERDRAW`.

351:   Collective

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

362:   Output Parameter:
363: . viewer - the `PetscViewer`

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

374:   Level: beginner

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

380:   Format options include\:
381: + `PETSC_VIEWER_DRAW_BASIC` - displays with basic format
382: - `PETSC_VIEWER_DRAW_LG`    - displays using a line graph

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

521:   Level: beginner

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

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

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

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

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

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

557:   Not Collective

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

562:   Level: intermediate

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

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

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

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

587:   Not Collective

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

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

595:   Level: intermediate

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

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

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

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

630:   Not Collective

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

636:   Level: intermediate

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

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

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

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

662:   Not Collective

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

668:   Level: intermediate

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

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

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

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

690:   Not Collective

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

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

698:   Level: intermediate

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

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

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

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

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

730:      Collective

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

735:      Level: intermediate

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

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

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

753:   PetscFunctionBegin;
754:   ierr = PetscCommDuplicate(comm, &ncomm, NULL);
755:   if (ierr) {
756:     ierr = PetscError(PETSC_COMM_SELF, __LINE__, "PETSC_VIEWER_DRAW_", __FILE__, PETSC_ERR_PLIB, PETSC_ERROR_INITIAL, " ");
757:     PetscFunctionReturn(NULL);
758:   }
759:   if (Petsc_Viewer_Draw_keyval == MPI_KEYVAL_INVALID) {
760:     mpi_ierr = MPI_Comm_create_keyval(MPI_COMM_NULL_COPY_FN, MPI_COMM_NULL_DELETE_FN, &Petsc_Viewer_Draw_keyval, NULL);
761:     if (mpi_ierr) {
762:       ierr = PetscError(PETSC_COMM_SELF, __LINE__, "PETSC_VIEWER_DRAW_", __FILE__, PETSC_ERR_PLIB, PETSC_ERROR_INITIAL, " ");
763:       PetscFunctionReturn(NULL);
764:     }
765:   }
766:   mpi_ierr = MPI_Comm_get_attr(ncomm, Petsc_Viewer_Draw_keyval, (void **)&viewer, &flag);
767:   if (mpi_ierr) {
768:     ierr = PetscError(PETSC_COMM_SELF, __LINE__, "PETSC_VIEWER_DRAW_", __FILE__, PETSC_ERR_PLIB, PETSC_ERROR_INITIAL, " ");
769:     PetscFunctionReturn(NULL);
770:   }
771:   if (!flag) { /* PetscViewer not yet created */
772:     ierr                              = PetscViewerDrawOpen(ncomm, NULL, NULL, PETSC_DECIDE, PETSC_DECIDE, 300, 300, &viewer);
773:     ((PetscObject)viewer)->persistent = PETSC_TRUE;
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:     ierr = PetscObjectRegisterDestroy((PetscObject)viewer);
779:     if (ierr) {
780:       ierr = PetscError(PETSC_COMM_SELF, __LINE__, "PETSC_VIEWER_DRAW_", __FILE__, PETSC_ERR_PLIB, PETSC_ERROR_REPEAT, " ");
781:       PetscFunctionReturn(NULL);
782:     }
783:     mpi_ierr = MPI_Comm_set_attr(ncomm, Petsc_Viewer_Draw_keyval, (void *)viewer);
784:     if (mpi_ierr) {
785:       ierr = PetscError(PETSC_COMM_SELF, __LINE__, "PETSC_VIEWER_DRAW_", __FILE__, PETSC_ERR_PLIB, PETSC_ERROR_INITIAL, " ");
786:       PetscFunctionReturn(NULL);
787:     }
788:   }
789:   ierr = PetscCommDestroy(&ncomm);
790:   if (ierr) {
791:     ierr = PetscError(PETSC_COMM_SELF, __LINE__, "PETSC_VIEWER_DRAW_", __FILE__, PETSC_ERR_PLIB, PETSC_ERROR_REPEAT, " ");
792:     PetscFunctionReturn(NULL);
793:   }
794:   PetscFunctionReturn(viewer);
795: }

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

800:   Collective

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

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

810:   Level: intermediate

812:   Note:
813:   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
814:   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
815:   this viewer. Otherwise the color to physical value meaning changes with each new image if this is not set.

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

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

830:   vdraw->nbounds = nbounds;
831:   PetscCall(PetscFree(vdraw->bounds));
832:   PetscCall(PetscMalloc1(2 * nbounds, &vdraw->bounds));
833:   PetscCall(PetscArraycpy(vdraw->bounds, bounds, 2 * nbounds));
834:   PetscFunctionReturn(PETSC_SUCCESS);
835: }

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

840:   Collective

842:   Input Parameter:
843: . viewer - the `PetscViewer` (created with `PetscViewerDrawOpen()`)

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

849:   Level: intermediate

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

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

868:   if (nbounds) *nbounds = vdraw->nbounds;
869:   if (bounds) *bounds = vdraw->bounds;
870:   PetscFunctionReturn(PETSC_SUCCESS);
871: }