Date: 2025-03-29T05:58:43+00:00

Actual source code: drawv.c

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

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

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

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

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

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

     40:   Logically Collective

     42:   Input Parameters:
     43: + viewer       - the `PetscViewer` (created with `PetscViewerDrawOpen()`)
     44: - windownumber - how much to add to the base

     46:   Level: developer

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

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

     58:   PetscFunctionBegin;
     61:   PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERDRAW, &isdraw));
     62:   PetscCheck(isdraw, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Must be draw type PetscViewer");
     63:   vdraw = (PetscViewer_Draw *)viewer->data;

     65:   PetscCheck(windownumber + vdraw->draw_base >= 0, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Resulting base %" PetscInt_FMT " cannot be negative", windownumber + vdraw->draw_base);
     66:   vdraw->draw_base += windownumber;
     67:   PetscFunctionReturn(PETSC_SUCCESS);
     68: }

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

     73:   Logically Collective

     75:   Input Parameters:
     76: + viewer       - the `PetscViewer` (created with `PetscViewerDrawOpen()`)
     77: - windownumber - value to set the base

     79:   Level: developer

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

     84: .seealso: [](sec_viewers), `PetscViewerDrawGetLG()`, `PetscViewerDrawGetAxis()`, `PetscViewerDrawOpen()`, `PetscViewerDrawGetDraw()`, `PetscViewerDrawBaseAdd()`
     85: @*/
     86: PetscErrorCode PetscViewerDrawBaseSet(PetscViewer viewer, PetscInt windownumber)
     87: {
     88:   PetscViewer_Draw *vdraw;
     89:   PetscBool         isdraw;

     91:   PetscFunctionBegin;
     94:   PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERDRAW, &isdraw));
     95:   PetscCheck(isdraw, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Must be draw type PetscViewer");
     96:   vdraw = (PetscViewer_Draw *)viewer->data;

     98:   PetscCheck(windownumber >= 0, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Resulting base %" PetscInt_FMT " cannot be negative", windownumber);
     99:   vdraw->draw_base = windownumber;
    100:   PetscFunctionReturn(PETSC_SUCCESS);
    101: }

    103: PetscErrorCode PetscViewerDrawResize(PetscViewer v, int w, int h)
    104: {
    105:   PetscViewer_Draw *vdraw;
    106:   PetscBool         isdraw;

    108:   PetscFunctionBegin;
    110:   PetscCall(PetscObjectTypeCompare((PetscObject)v, PETSCVIEWERDRAW, &isdraw));
    111:   if (!isdraw) PetscFunctionReturn(PETSC_SUCCESS);
    112:   vdraw = (PetscViewer_Draw *)v->data;

    114:   if (w >= 1) vdraw->w = w;
    115:   if (h >= 1) vdraw->h = h;
    116:   PetscFunctionReturn(PETSC_SUCCESS);
    117: }

    119: PetscErrorCode PetscViewerDrawSetInfo(PetscViewer v, const char display[], const char title[], int x, int y, int w, int h)
    120: {
    121:   PetscViewer_Draw *vdraw;
    122:   PetscBool         isdraw;

    124:   PetscFunctionBegin;
    126:   PetscCall(PetscObjectTypeCompare((PetscObject)v, PETSCVIEWERDRAW, &isdraw));
    127:   if (!isdraw) PetscFunctionReturn(PETSC_SUCCESS);
    128:   vdraw = (PetscViewer_Draw *)v->data;

    130:   PetscCall(PetscStrallocpy(display, &vdraw->display));
    131:   PetscCall(PetscStrallocpy(title, &vdraw->title));
    132:   if (w >= 1) vdraw->w = w;
    133:   if (h >= 1) vdraw->h = h;
    134:   PetscFunctionReturn(PETSC_SUCCESS);
    135: }

    137: PetscErrorCode PetscViewerDrawSetTitle(PetscViewer v, const char title[])
    138: {
    139:   PetscViewer_Draw *vdraw;
    140:   PetscBool         isdraw;

    142:   PetscFunctionBegin;
    144:   PetscCall(PetscObjectTypeCompare((PetscObject)v, PETSCVIEWERDRAW, &isdraw));
    145:   if (!isdraw) PetscFunctionReturn(PETSC_SUCCESS);
    146:   vdraw = (PetscViewer_Draw *)v->data;

    148:   PetscCall(PetscFree(vdraw->title));
    149:   PetscCall(PetscStrallocpy(title, &vdraw->title));
    150:   PetscFunctionReturn(PETSC_SUCCESS);
    151: }

    153: PetscErrorCode PetscViewerDrawGetTitle(PetscViewer v, const char *title[])
    154: {
    155:   PetscViewer_Draw *vdraw;
    156:   PetscBool         isdraw;

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

    164:   *title = vdraw->title;
    165:   PetscFunctionReturn(PETSC_SUCCESS);
    166: }

    168: /*@
    169:   PetscViewerDrawOpen - Opens a `PetscDraw` window for use as a `PetscViewer` with type
    170:   `PETSCVIEWERDRAW`.

    172:   Collective

    174:   Input Parameters:
    175: + comm    - communicator that will share window
    176: . display - the X display on which to open, or `NULL` for the local machine
    177: . title   - the title to put in the title bar, or `NULL` for no title
    178: . x       - horizontal screen coordinate of the upper left corner of window, or use `PETSC_DECIDE`
    179: . y       - vertical screen coordinate of the upper left corner of window, or use `PETSC_DECIDE`
    180: . w       - window width in pixels, or may use `PETSC_DECIDE` or `PETSC_DRAW_FULL_SIZE`, `PETSC_DRAW_HALF_SIZE`,`PETSC_DRAW_THIRD_SIZE`, `PETSC_DRAW_QUARTER_SIZE`
    181: - h       - window height in pixels, or may use `PETSC_DECIDE` or `PETSC_DRAW_FULL_SIZE`, `PETSC_DRAW_HALF_SIZE`,`PETSC_DRAW_THIRD_SIZE`, `PETSC_DRAW_QUARTER_SIZE`

    183:   Output Parameter:
    184: . viewer - the `PetscViewer`

    186:   Options Database Keys:
    187: + -draw_type          - use x or null
    188: . -nox                - Disables all x-windows output
    189: . -display <name>     - Specifies name of machine for the X display
    190: . -geometry <x,y,w,h> - allows setting the window location and size
    191: - -draw_pause <pause> - Sets time (in seconds) that the
    192:      program pauses after PetscDrawPause() has been called
    193:      (0 is default, -1 implies until user input).

    195:   Level: beginner

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

    201:   Format options include\:
    202: + `PETSC_VIEWER_DRAW_BASIC` - displays with basic format
    203: - `PETSC_VIEWER_DRAW_LG`    - displays using a line graph

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

    341:   Level: beginner

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

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

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

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

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

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

    377:   Not Collective

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

    382:   Level: intermediate

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

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

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

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

    407:   Not Collective

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

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

    415:   Level: intermediate

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

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

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

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

    450:   Not Collective

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

    456:   Level: intermediate

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

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

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

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

    482:   Not Collective

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

    488:   Level: intermediate

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

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

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

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

    510:   Not Collective

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

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

    518:   Level: intermediate

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

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

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

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

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

    550:    Collective

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

    555:    Level: intermediate

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

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

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

    574:   PetscFunctionBegin;
    575:   PetscCallNull(PetscCommDuplicate(comm, &ncomm, NULL));
    576:   if (Petsc_Viewer_Draw_keyval == MPI_KEYVAL_INVALID) { PetscCallMPINull(MPI_Comm_create_keyval(MPI_COMM_NULL_COPY_FN, MPI_COMM_NULL_DELETE_FN, &Petsc_Viewer_Draw_keyval, NULL)); }
    577:   PetscCallMPINull(MPI_Comm_get_attr(ncomm, Petsc_Viewer_Draw_keyval, (void **)&viewer, &flag));
    578:   if (!flag) { /* PetscViewer not yet created */
    579:     PetscCallNull(PetscViewerDrawOpen(ncomm, NULL, NULL, PETSC_DECIDE, PETSC_DECIDE, 300, 300, &viewer));
    580:     PetscCallNull(PetscObjectRegisterDestroy((PetscObject)viewer));
    581:     PetscCallMPINull(MPI_Comm_set_attr(ncomm, Petsc_Viewer_Draw_keyval, (void *)viewer));
    582:   }
    583:   PetscCallNull(PetscCommDestroy(&ncomm));
    584:   PetscFunctionReturn(viewer);
    585: }

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

    590:   Collective

    592:   Input Parameters:
    593: + viewer  - the Petsc`Viewer` (created with `PetscViewerDrawOpen()`)
    594: . nbounds - number of plots that can be made with this viewer, for example the dof passed to `DMDACreate()`
    595: - bounds  - the actual bounds, the size of this is 2*`nbounds`, the values are stored in the order min F_0, max F_0, min F_1, max F_1, .....

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

    600:   Level: intermediate

    602:   Note:
    603:   this determines the colors used in 2d contour plots generated with VecView() for `DMDA` in 2d. Any values in the vector below or above the
    604:   bounds are moved to the bound value before plotting. In this way the color index from color to physical value remains the same for all plots generated with
    605:   this viewer. Otherwise the color to physical value meaning changes with each new image if this is not set.

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

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

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

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

    630:   Collective

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

    635:   Output Parameters:
    636: + nbounds - number of plots that can be made with this viewer, for example the dof passed to `DMDACreate()`
    637: - bounds  - the actual bounds, the size of this is 2*`nbounds`, the values are stored in the order min F_0, max F_0, min F_1, max F_1, .....

    639:   Level: intermediate

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

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

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

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

    666:   Collective

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

    680:   Level: developer

    682: .seealso: `PetscViewer()`, `PETSCVIEWERDRAW`, `PetscViewerDrawGetDrawLG()`, `PetscViewerDrawOpen()`, `PetscViewerDrawSetInfo()`
    683: @*/
    684: PetscErrorCode PetscViewerMonitorLGSetUp(PetscViewer viewer, const char host[], const char title[], const char metric[], PetscInt l, const char *names[], int x, int y, int m, int n) PeNS
    685: {
    686:   PetscDrawAxis axis;
    687:   PetscDrawLG   lg;

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