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:   PetscErrorCode   ierr;
      8:   PetscInt         i;
      9:   PetscViewer_Draw *vdraw = (PetscViewer_Draw*)v->data;

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

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

     34:   for (i=0; i<vdraw->draw_max; i++) {
     35:     if (vdraw->draw[i]) {PetscDrawFlush(vdraw->draw[i]);}
     36:   }
     37:   return(0);
     38: }

     40: /*@C
     41:     PetscViewerDrawGetDraw - Returns PetscDraw object from PetscViewer object.
     42:     This PetscDraw object may then be used to perform graphics using
     43:     PetscDrawXXX() commands.

     45:     Collective on PetscViewer

     47:     Input Parameters:
     48: +   viewer - the PetscViewer (created with PetscViewerDrawOpen())
     49: -   windownumber - indicates which subwindow (usually 0)

     51:     Ouput Parameter:
     52: .   draw - the draw object

     54:     Level: intermediate

     57: .seealso: PetscViewerDrawGetLG(), PetscViewerDrawGetAxis(), PetscViewerDrawOpen()
     58: @*/
     59: PetscErrorCode  PetscViewerDrawGetDraw(PetscViewer viewer,PetscInt windownumber,PetscDraw *draw)
     60: {
     61:   PetscViewer_Draw *vdraw;
     62:   PetscErrorCode   ierr;
     63:   PetscBool        isdraw;

     69:   PetscObjectTypeCompare((PetscObject)viewer,PETSCVIEWERDRAW,&isdraw);
     70:   if (!isdraw) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_WRONG,"Must be draw type PetscViewer");
     71:   if (windownumber < 0) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_OUTOFRANGE,"Window number cannot be negative");
     72:   vdraw = (PetscViewer_Draw*)viewer->data;

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

     82:     vdraw->draw_max = 2*windownumber;

     84:     PetscCalloc3(vdraw->draw_max,&vdraw->draw,vdraw->draw_max,&vdraw->drawlg,vdraw->draw_max,&vdraw->drawaxis);
     85:     PetscArraycpy(vdraw->draw,tdraw,draw_max);
     86:     PetscArraycpy(vdraw->drawlg,drawlg,draw_max);
     87:     PetscArraycpy(vdraw->drawaxis,drawaxis,draw_max);
     88:     PetscFree3(tdraw,drawlg,drawaxis);
     89:   }

     91:   if (!vdraw->draw[windownumber]) {
     92:     char *title = vdraw->title, tmp_str[128];
     93:     if (windownumber) {
     94:       PetscSNPrintf(tmp_str,sizeof(tmp_str),"%s:%d",vdraw->title?vdraw->title:"",windownumber);
     95:       title = tmp_str;
     96:     }
     97:     PetscDrawCreate(PetscObjectComm((PetscObject)viewer),vdraw->display,title,PETSC_DECIDE,PETSC_DECIDE,vdraw->w,vdraw->h,&vdraw->draw[windownumber]);
     98:     PetscLogObjectParent((PetscObject)viewer,(PetscObject)vdraw->draw[windownumber]);
     99:     if (vdraw->drawtype) {
    100:       PetscDrawSetType(vdraw->draw[windownumber],vdraw->drawtype);
    101:     }
    102:     PetscDrawSetPause(vdraw->draw[windownumber],vdraw->pause);
    103:     PetscDrawSetOptionsPrefix(vdraw->draw[windownumber],((PetscObject)viewer)->prefix);
    104:     PetscDrawSetFromOptions(vdraw->draw[windownumber]);
    105:   }
    106:   if (draw) *draw = vdraw->draw[windownumber];
    108:   return(0);
    109: }

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

    114:     Logically Collective on PetscViewer

    116:     Input Parameters:
    117: +  viewer - the PetscViewer (created with PetscViewerDrawOpen())
    118: -   windownumber - how much to add to the base

    120:     Level: developer

    123: .seealso: PetscViewerDrawGetLG(), PetscViewerDrawGetAxis(), PetscViewerDrawOpen(), PetscViewerDrawGetDraw(), PetscViewerDrawBaseSet()
    124: @*/
    125: PetscErrorCode  PetscViewerDrawBaseAdd(PetscViewer viewer,PetscInt windownumber)
    126: {
    127:   PetscViewer_Draw *vdraw;
    128:   PetscErrorCode   ierr;
    129:   PetscBool        isdraw;

    134:   PetscObjectTypeCompare((PetscObject)viewer,PETSCVIEWERDRAW,&isdraw);
    135:   if (!isdraw) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_WRONG,"Must be draw type PetscViewer");
    136:   vdraw = (PetscViewer_Draw*)viewer->data;

    138:   if (windownumber + vdraw->draw_base < 0) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_ARG_OUTOFRANGE,"Resulting base %D cannot be negative",windownumber+vdraw->draw_base);
    139:   vdraw->draw_base += windownumber;
    140:   return(0);
    141: }

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

    146:     Logically Collective on PetscViewer

    148:     Input Parameters:
    149: +   viewer - the PetscViewer (created with PetscViewerDrawOpen())
    150: -   windownumber - value to set the base

    152:     Level: developer

    155: .seealso: PetscViewerDrawGetLG(), PetscViewerDrawGetAxis(), PetscViewerDrawOpen(), PetscViewerDrawGetDraw(), PetscViewerDrawBaseAdd()
    156: @*/
    157: PetscErrorCode  PetscViewerDrawBaseSet(PetscViewer viewer,PetscInt windownumber)
    158: {
    159:   PetscViewer_Draw *vdraw;
    160:   PetscErrorCode   ierr;
    161:   PetscBool        isdraw;

    166:   PetscObjectTypeCompare((PetscObject)viewer,PETSCVIEWERDRAW,&isdraw);
    167:   if (!isdraw) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_WRONG,"Must be draw type PetscViewer");
    168:   vdraw = (PetscViewer_Draw*)viewer->data;

    170:   if (windownumber < 0) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_ARG_OUTOFRANGE,"Resulting base %D cannot be negative",windownumber);
    171:   vdraw->draw_base = windownumber;
    172:   return(0);
    173: }

    175: /*@C
    176:     PetscViewerDrawGetDrawLG - Returns PetscDrawLG object from PetscViewer object.
    177:     This PetscDrawLG object may then be used to perform graphics using
    178:     PetscDrawLGXXX() commands.

    180:     Collective on PetscViewer

    182:     Input Parameter:
    183: +   PetscViewer - the PetscViewer (created with PetscViewerDrawOpen())
    184: -   windownumber - indicates which subwindow (usually 0)

    186:     Ouput Parameter:
    187: .   draw - the draw line graph object

    189:     Level: intermediate

    191: .seealso: PetscViewerDrawGetDraw(), PetscViewerDrawGetAxis(), PetscViewerDrawOpen()
    192: @*/
    193: PetscErrorCode  PetscViewerDrawGetDrawLG(PetscViewer viewer,PetscInt windownumber,PetscDrawLG *drawlg)
    194: {
    195:   PetscErrorCode   ierr;
    196:   PetscBool        isdraw;
    197:   PetscViewer_Draw *vdraw;

    203:   PetscObjectTypeCompare((PetscObject)viewer,PETSCVIEWERDRAW,&isdraw);
    204:   if (!isdraw) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_WRONG,"Must be draw type PetscViewer");
    205:   if (windownumber < 0) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_OUTOFRANGE,"Window number cannot be negative");
    206:   vdraw = (PetscViewer_Draw*)viewer->data;

    208:   if (windownumber+vdraw->draw_base >= vdraw->draw_max || !vdraw->draw[windownumber+vdraw->draw_base]) {
    209:     PetscViewerDrawGetDraw(viewer,windownumber,NULL);
    210:   }
    211:   if (!vdraw->drawlg[windownumber+vdraw->draw_base]) {
    212:     PetscDrawLGCreate(vdraw->draw[windownumber+vdraw->draw_base],1,&vdraw->drawlg[windownumber+vdraw->draw_base]);
    213:     PetscLogObjectParent((PetscObject)viewer,(PetscObject)vdraw->drawlg[windownumber+vdraw->draw_base]);
    214:     PetscDrawLGSetFromOptions(vdraw->drawlg[windownumber+vdraw->draw_base]);
    215:   }
    216:   *drawlg = vdraw->drawlg[windownumber+vdraw->draw_base];
    217:   return(0);
    218: }

    220: /*@C
    221:     PetscViewerDrawGetDrawAxis - Returns PetscDrawAxis object from PetscViewer object.
    222:     This PetscDrawAxis object may then be used to perform graphics using
    223:     PetscDrawAxisXXX() commands.

    225:     Collective on PetscViewer

    227:     Input Parameter:
    228: +   viewer - the PetscViewer (created with PetscViewerDrawOpen()
    229: -   windownumber - indicates which subwindow (usually 0)

    231:     Ouput Parameter:
    232: .   drawaxis - the draw axis object

    234:     Level: advanced

    236: .seealso: PetscViewerDrawGetDraw(), PetscViewerDrawGetLG(), PetscViewerDrawOpen()
    237: @*/
    238: PetscErrorCode  PetscViewerDrawGetDrawAxis(PetscViewer viewer,PetscInt windownumber,PetscDrawAxis *drawaxis)
    239: {
    240:   PetscErrorCode   ierr;
    241:   PetscBool        isdraw;
    242:   PetscViewer_Draw *vdraw;

    248:   PetscObjectTypeCompare((PetscObject)viewer,PETSCVIEWERDRAW,&isdraw);
    249:   if (!isdraw) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_WRONG,"Must be draw type PetscViewer");
    250:   if (windownumber < 0) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_OUTOFRANGE,"Window number cannot be negative");
    251:   vdraw = (PetscViewer_Draw*)viewer->data;

    253:   if (windownumber+vdraw->draw_base >= vdraw->draw_max || !vdraw->draw[windownumber+vdraw->draw_base]) {
    254:     PetscViewerDrawGetDraw(viewer,windownumber,NULL);
    255:   }
    256:   if (!vdraw->drawaxis[windownumber+vdraw->draw_base]) {
    257:     PetscDrawAxisCreate(vdraw->draw[windownumber+vdraw->draw_base],&vdraw->drawaxis[windownumber+vdraw->draw_base]);
    258:     PetscLogObjectParent((PetscObject)viewer,(PetscObject)vdraw->drawaxis[windownumber+vdraw->draw_base]);
    259:   }
    260:   *drawaxis = vdraw->drawaxis[windownumber+vdraw->draw_base];
    261:   return(0);
    262: }

    264: PetscErrorCode  PetscViewerDrawResize(PetscViewer v,int w,int h)
    265: {
    266:   PetscErrorCode   ierr;
    267:   PetscViewer_Draw *vdraw;
    268:   PetscBool        isdraw;

    272:   PetscObjectTypeCompare((PetscObject)v,PETSCVIEWERDRAW,&isdraw);
    273:   if (!isdraw) return(0);
    274:   vdraw = (PetscViewer_Draw*)v->data;

    276:   if (w >= 1) vdraw->w = w;
    277:   if (h >= 1) vdraw->h = h;
    278:   return(0);
    279: }

    281: PetscErrorCode  PetscViewerDrawSetInfo(PetscViewer v,const char display[],const char title[],int x,int y,int w,int h)
    282: {
    283:   PetscErrorCode   ierr;
    284:   PetscViewer_Draw *vdraw;
    285:   PetscBool        isdraw;

    289:   PetscObjectTypeCompare((PetscObject)v,PETSCVIEWERDRAW,&isdraw);
    290:   if (!isdraw) return(0);
    291:   vdraw = (PetscViewer_Draw*)v->data;

    293:   PetscStrallocpy(display,&vdraw->display);
    294:   PetscStrallocpy(title,&vdraw->title);
    295:   if (w >= 1) vdraw->w = w;
    296:   if (h >= 1) vdraw->h = h;
    297:   return(0);
    298: }

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

    308:   PetscObjectTypeCompare((PetscObject)v,PETSCVIEWERDRAW,&isdraw);
    309:   if (!isdraw) return(0);
    310:   vdraw = (PetscViewer_Draw*)v->data;

    312:   PetscFree(vdraw->drawtype);
    313:   PetscStrallocpy(drawtype,(char**)&vdraw->drawtype);
    314:   return(0);
    315: }

    317: PetscErrorCode PetscViewerDrawGetDrawType(PetscViewer v,PetscDrawType *drawtype)
    318: {
    319:   PetscErrorCode   ierr;
    320:   PetscViewer_Draw *vdraw;
    321:   PetscBool        isdraw;

    325:   PetscObjectTypeCompare((PetscObject)v,PETSCVIEWERDRAW,&isdraw);
    326:   if (!isdraw) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_WRONG,"Must be draw type PetscViewer");
    327:   vdraw = (PetscViewer_Draw*)v->data;

    329:   *drawtype = vdraw->drawtype;
    330:   return(0);
    331: }

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

    341:   PetscObjectTypeCompare((PetscObject)v,PETSCVIEWERDRAW,&isdraw);
    342:   if (!isdraw) return(0);
    343:   vdraw = (PetscViewer_Draw*)v->data;

    345:   PetscFree(vdraw->title);
    346:   PetscStrallocpy(title,&vdraw->title);
    347:   return(0);
    348: }

    350: PetscErrorCode PetscViewerDrawGetTitle(PetscViewer v,const char *title[])
    351: {
    352:   PetscErrorCode   ierr;
    353:   PetscViewer_Draw *vdraw;
    354:   PetscBool        isdraw;

    358:   PetscObjectTypeCompare((PetscObject)v,PETSCVIEWERDRAW,&isdraw);
    359:   if (!isdraw) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_WRONG,"Must be draw type PetscViewer");
    360:   vdraw = (PetscViewer_Draw*)v->data;

    362:   *title = vdraw->title;
    363:   return(0);
    364: }

    366: /*@C
    367:    PetscViewerDrawOpen - Opens a window for use as a PetscViewer. If you want to
    368:    do graphics in this window, you must call PetscViewerDrawGetDraw() and
    369:    perform the graphics on the PetscDraw object.

    371:    Collective

    373:    Input Parameters:
    374: +  comm - communicator that will share window
    375: .  display - the X display on which to open, or null for the local machine
    376: .  title - the title to put in the title bar, or null for no title
    377: .  x, y - the screen coordinates of the upper left corner of window, or use PETSC_DECIDE
    378: -  w, h - window width and height in pixels, or may use PETSC_DECIDE or PETSC_DRAW_FULL_SIZE, PETSC_DRAW_HALF_SIZE,
    379:           PETSC_DRAW_THIRD_SIZE, PETSC_DRAW_QUARTER_SIZE

    381:    Output Parameters:
    382: . viewer - the PetscViewer

    384:    Format Options:
    385: +  PETSC_VIEWER_DRAW_BASIC - displays with basic format
    386: -  PETSC_VIEWER_DRAW_LG    - displays using a line graph

    388:    Options Database Keys:
    389: +  -draw_type - use x or null
    390: .  -nox - Disables all x-windows output
    391: .  -display <name> - Specifies name of machine for the X display
    392: .  -geometry <x,y,w,h> - allows setting the window location and size
    393: -  -draw_pause <pause> - Sets time (in seconds) that the
    394:      program pauses after PetscDrawPause() has been called
    395:      (0 is default, -1 implies until user input).

    397:    Level: beginner

    399:    Notes:
    400:      PetscViewerDrawOpen() calls PetscDrawCreate(), so see the manual pages for PetscDrawCreate()

    402:    Note for Fortran Programmers:
    403:    Whenever indicating null character data in a Fortran code,
    404:    PETSC_NULL_CHARACTER must be employed; using NULL is not
    405:    correct for character data!  Thus, PETSC_NULL_CHARACTER can be
    406:    used for the display and title input parameters.

    410: .seealso: PetscDrawCreate(), PetscViewerDestroy(), PetscViewerDrawGetDraw(), PetscViewerCreate(), PETSC_VIEWER_DRAW_,
    411:           PETSC_VIEWER_DRAW_WORLD, PETSC_VIEWER_DRAW_SELF
    412: @*/
    413: PetscErrorCode  PetscViewerDrawOpen(MPI_Comm comm,const char display[],const char title[],int x,int y,int w,int h,PetscViewer *viewer)
    414: {

    418:   PetscViewerCreate(comm,viewer);
    419:   PetscViewerSetType(*viewer,PETSCVIEWERDRAW);
    420:   PetscViewerDrawSetInfo(*viewer,display,title,x,y,w,h);
    421:   return(0);
    422: }

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

    426: PetscErrorCode PetscViewerGetSubViewer_Draw(PetscViewer viewer,MPI_Comm comm,PetscViewer *sviewer)
    427: {
    428:   PetscErrorCode   ierr;
    429:   PetscMPIInt      rank;
    430:   PetscInt         i;
    431:   PetscViewer_Draw *vdraw = (PetscViewer_Draw*)viewer->data,*svdraw;

    434:   if (vdraw->singleton_made) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ORDER,"Trying to get SubViewer without first restoring previous");
    435:   /* only processor zero can use the PetscViewer draw singleton */
    436:   if (sviewer) *sviewer = NULL;
    437:   MPI_Comm_rank(PetscObjectComm((PetscObject)viewer),&rank);
    438:   if (!rank) {
    439:     PetscMPIInt flg;
    440:     PetscDraw   draw,sdraw;

    442:     MPI_Comm_compare(PETSC_COMM_SELF,comm,&flg);
    443:     if (flg != MPI_IDENT && flg != MPI_CONGRUENT) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_SUP,"PetscViewerGetSubViewer() for PETSCVIEWERDRAW requires a singleton MPI_Comm");
    444:     PetscViewerCreate(comm,sviewer);
    445:     PetscViewerSetType(*sviewer,PETSCVIEWERDRAW);
    446:     svdraw = (PetscViewer_Draw*)(*sviewer)->data;
    447:     (*sviewer)->format = viewer->format;
    448:     for (i=0; i<vdraw->draw_max; i++) { /* XXX this is wrong if svdraw->draw_max (initially 5) < vdraw->draw_max */
    449:       if (vdraw->draw[i]) {PetscDrawGetSingleton(vdraw->draw[i],&svdraw->draw[i]);}
    450:     }
    451:     PetscViewerDrawGetDraw(viewer,0,&draw);
    452:     PetscViewerDrawGetDraw(*sviewer,0,&sdraw);
    453:     if (draw->savefilename) {
    454:       PetscDrawSetSave(sdraw,draw->savefilename);
    455:       sdraw->savefilecount = draw->savefilecount;
    456:       sdraw->savesinglefile = draw->savesinglefile;
    457:       sdraw->savemoviefps = draw->savemoviefps;
    458:       sdraw->saveonclear = draw->saveonclear;
    459:       sdraw->saveonflush = draw->saveonflush;
    460:     }
    461:     if (draw->savefinalfilename) {PetscDrawSetSaveFinalImage(sdraw,draw->savefinalfilename);}
    462:   } else {
    463:     PetscDraw draw;
    464:     PetscViewerDrawGetDraw(viewer,0,&draw);
    465:   }
    466:   vdraw->singleton_made = PETSC_TRUE;
    467:   return(0);
    468: }

    470: PetscErrorCode PetscViewerRestoreSubViewer_Draw(PetscViewer viewer,MPI_Comm comm,PetscViewer *sviewer)
    471: {
    472:   PetscErrorCode   ierr;
    473:   PetscMPIInt      rank;
    474:   PetscInt         i;
    475:   PetscViewer_Draw *vdraw = (PetscViewer_Draw*)viewer->data,*svdraw;

    478:   if (!vdraw->singleton_made) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ORDER,"Trying to restore a singleton that was not gotten");
    479:   MPI_Comm_rank(PetscObjectComm((PetscObject)viewer),&rank);
    480:   if (!rank) {
    481:     PetscDraw draw,sdraw;

    483:     PetscViewerDrawGetDraw(viewer,0,&draw);
    484:     PetscViewerDrawGetDraw(*sviewer,0,&sdraw);
    485:     if (draw->savefilename) {
    486:       draw->savefilecount = sdraw->savefilecount;
    487:       MPI_Bcast(&draw->savefilecount,1,MPIU_INT,0,PetscObjectComm((PetscObject)draw));
    488:     }
    489:     svdraw = (PetscViewer_Draw*)(*sviewer)->data;
    490:     for (i=0; i<vdraw->draw_max; i++) {
    491:       if (vdraw->draw[i] && svdraw->draw[i]) {
    492:         PetscDrawRestoreSingleton(vdraw->draw[i],&svdraw->draw[i]);
    493:       }
    494:     }
    495:     PetscFree3(svdraw->draw,svdraw->drawlg,svdraw->drawaxis);
    496:     PetscFree((*sviewer)->data);
    497:     PetscHeaderDestroy(sviewer);
    498:   } else {
    499:     PetscDraw draw;

    501:     PetscViewerDrawGetDraw(viewer,0,&draw);
    502:     if (draw->savefilename) {
    503:       MPI_Bcast(&draw->savefilecount,1,MPIU_INT,0,PetscObjectComm((PetscObject)draw));
    504:     }
    505:   }

    507:   vdraw->singleton_made = PETSC_FALSE;
    508:   return(0);
    509: }

    511: PetscErrorCode PetscViewerSetFromOptions_Draw(PetscOptionItems *PetscOptionsObject,PetscViewer v)
    512: {
    514:   PetscReal      bounds[16];
    515:   PetscInt       nbounds = 16;
    516:   PetscBool      flg;

    519:   PetscOptionsHead(PetscOptionsObject,"Draw PetscViewer Options");
    520:   PetscOptionsRealArray("-draw_bounds","Bounds to put on plots axis","PetscViewerDrawSetBounds",bounds,&nbounds,&flg);
    521:   if (flg) {
    522:     PetscViewerDrawSetBounds(v,nbounds/2,bounds);
    523:   }
    524:   PetscOptionsTail();
    525:   return(0);
    526: }

    528: PetscErrorCode PetscViewerView_Draw(PetscViewer viewer,PetscViewer v)
    529: {
    530:   PetscErrorCode   ierr;
    531:   PetscDraw        draw;
    532:   PetscInt         i;
    533:   PetscViewer_Draw *vdraw = (PetscViewer_Draw*)viewer->data;

    536:   /*  If the PetscViewer has just been created then no vdraw->draw yet
    537:       exists so this will not actually call the viewer on any draws. */
    538:   for (i=0; i<vdraw->draw_base; i++) {
    539:     if (vdraw->draw[i]) {
    540:       PetscViewerDrawGetDraw(viewer,i,&draw);
    541:       PetscDrawView(draw,v);
    542:     }
    543:   }
    544:   return(0);
    545: }

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

    551: .seealso:  PetscViewerDrawOpen(), PetscViewerDrawGetDraw(), PETSC_VIEWER_DRAW_(),PETSC_VIEWER_DRAW_SELF, PETSC_VIEWER_DRAW_WORLD,
    552:            PetscViewerCreate(), PetscViewerASCIIOpen(), PetscViewerBinaryOpen(), PETSCVIEWERBINARY,
    553:            PetscViewerMatlabOpen(), VecView(), DMView(), PetscViewerMatlabPutArray(), PETSCVIEWERASCII, PETSCVIEWERMATLAB,
    554:            PetscViewerFileSetName(), PetscViewerFileSetMode(), PetscViewerFormat, PetscViewerType, PetscViewerSetType()

    556:   Level: beginner

    558: M*/
    559: PETSC_EXTERN PetscErrorCode PetscViewerCreate_Draw(PetscViewer viewer)
    560: {
    561:   PetscErrorCode   ierr;
    562:   PetscViewer_Draw *vdraw;

    565:   PetscNewLog(viewer,&vdraw);
    566:   viewer->data = (void*)vdraw;

    568:   viewer->ops->flush            = PetscViewerFlush_Draw;
    569:   viewer->ops->view             = PetscViewerView_Draw;
    570:   viewer->ops->destroy          = PetscViewerDestroy_Draw;
    571:   viewer->ops->setfromoptions   = PetscViewerSetFromOptions_Draw;
    572:   viewer->ops->getsubviewer     = PetscViewerGetSubViewer_Draw;
    573:   viewer->ops->restoresubviewer = PetscViewerRestoreSubViewer_Draw;

    575:   /* these are created on the fly if requested */
    576:   vdraw->draw_max  = 5;
    577:   vdraw->draw_base = 0;
    578:   vdraw->w         = PETSC_DECIDE;
    579:   vdraw->h         = PETSC_DECIDE;

    581:   PetscCalloc3(vdraw->draw_max,&vdraw->draw,vdraw->draw_max,&vdraw->drawlg,vdraw->draw_max,&vdraw->drawaxis);
    582:   vdraw->singleton_made = PETSC_FALSE;
    583:   return(0);
    584: }

    586: /*@
    587:     PetscViewerDrawClear - Clears a PetscDraw graphic associated with a PetscViewer.

    589:     Not Collective

    591:     Input Parameter:
    592: .  viewer - the PetscViewer

    594:     Level: intermediate

    596: .seealso: PetscViewerDrawOpen(), PetscViewerDrawGetDraw(),

    598: @*/
    599: PetscErrorCode  PetscViewerDrawClear(PetscViewer viewer)
    600: {
    601:   PetscErrorCode   ierr;
    602:   PetscViewer_Draw *vdraw;
    603:   PetscBool        isdraw;
    604:   PetscInt         i;

    608:   PetscObjectTypeCompare((PetscObject)viewer,PETSCVIEWERDRAW,&isdraw);
    609:   if (!isdraw) return(0);
    610:   vdraw = (PetscViewer_Draw*)viewer->data;

    612:   for (i=0; i<vdraw->draw_max; i++) {
    613:     if (vdraw->draw[i]) {PetscDrawClear(vdraw->draw[i]);}
    614:   }
    615:   return(0);
    616: }

    618: /*@
    619:     PetscViewerDrawGetPause - Gets a pause for the first present draw

    621:     Not Collective

    623:     Input Parameter:
    624: .  viewer - the PetscViewer

    626:     Output Parameter:
    627: .  pause - the pause value

    629:     Level: intermediate

    631: .seealso: PetscViewerDrawOpen(), PetscViewerDrawGetDraw(),

    633: @*/
    634: PetscErrorCode  PetscViewerDrawGetPause(PetscViewer viewer,PetscReal *pause)
    635: {
    636:   PetscErrorCode   ierr;
    637:   PetscViewer_Draw *vdraw;
    638:   PetscBool        isdraw;
    639:   PetscInt         i;
    640:   PetscDraw        draw;

    644:   PetscObjectTypeCompare((PetscObject)viewer,PETSCVIEWERDRAW,&isdraw);
    645:   if (!isdraw) {*pause = 0.0; return(0);}
    646:   vdraw = (PetscViewer_Draw*)viewer->data;

    648:   for (i=0; i<vdraw->draw_max; i++) {
    649:     if (vdraw->draw[i]) {
    650:       PetscDrawGetPause(vdraw->draw[i],pause);
    651:       return(0);
    652:     }
    653:   }
    654:   /* none exist yet so create one and get its pause */
    655:   PetscViewerDrawGetDraw(viewer,0,&draw);
    656:   PetscDrawGetPause(draw,pause);
    657:   return(0);
    658: }

    660: /*@
    661:     PetscViewerDrawSetPause - Sets a pause for each PetscDraw in the viewer

    663:     Not Collective

    665:     Input Parameters:
    666: +  viewer - the PetscViewer
    667: -  pause - the pause value

    669:     Level: intermediate

    671: .seealso: PetscViewerDrawOpen(), PetscViewerDrawGetDraw(),

    673: @*/
    674: PetscErrorCode  PetscViewerDrawSetPause(PetscViewer viewer,PetscReal pause)
    675: {
    676:   PetscErrorCode   ierr;
    677:   PetscViewer_Draw *vdraw;
    678:   PetscBool        isdraw;
    679:   PetscInt         i;

    683:   PetscObjectTypeCompare((PetscObject)viewer,PETSCVIEWERDRAW,&isdraw);
    684:   if (!isdraw) return(0);
    685:   vdraw = (PetscViewer_Draw*)viewer->data;

    687:   vdraw->pause = pause;
    688:   for (i=0; i<vdraw->draw_max; i++) {
    689:     if (vdraw->draw[i]) {PetscDrawSetPause(vdraw->draw[i],pause);}
    690:   }
    691:   return(0);
    692: }

    695: /*@
    696:     PetscViewerDrawSetHold - Holds previous image when drawing new image

    698:     Not Collective

    700:     Input Parameters:
    701: +  viewer - the PetscViewer
    702: -  hold - indicates to hold or not

    704:     Level: intermediate

    706: .seealso: PetscViewerDrawOpen(), PetscViewerDrawGetDraw(),

    708: @*/
    709: PetscErrorCode  PetscViewerDrawSetHold(PetscViewer viewer,PetscBool hold)
    710: {
    711:   PetscErrorCode   ierr;
    712:   PetscViewer_Draw *vdraw;
    713:   PetscBool        isdraw;

    717:   PetscObjectTypeCompare((PetscObject)viewer,PETSCVIEWERDRAW,&isdraw);
    718:   if (!isdraw) return(0);
    719:   vdraw = (PetscViewer_Draw*)viewer->data;

    721:   vdraw->hold = hold;
    722:   return(0);
    723: }

    725: /*@
    726:     PetscViewerDrawGetHold - Checks if holds previous image when drawing new image

    728:     Not Collective

    730:     Input Parameter:
    731: .  viewer - the PetscViewer

    733:     Output Parameter:
    734: .  hold - indicates to hold or not

    736:     Level: intermediate

    738: .seealso: PetscViewerDrawOpen(), PetscViewerDrawGetDraw(),

    740: @*/
    741: PetscErrorCode  PetscViewerDrawGetHold(PetscViewer viewer,PetscBool *hold)
    742: {
    743:   PetscErrorCode   ierr;
    744:   PetscViewer_Draw *vdraw;
    745:   PetscBool        isdraw;

    749:   PetscObjectTypeCompare((PetscObject)viewer,PETSCVIEWERDRAW,&isdraw);
    750:   if (!isdraw) {*hold = PETSC_FALSE; return(0);}
    751:   vdraw = (PetscViewer_Draw*)viewer->data;

    753:   *hold = vdraw->hold;
    754:   return(0);
    755: }

    757: /* ---------------------------------------------------------------------*/
    758: /*
    759:     The variable Petsc_Viewer_Draw_keyval is used to indicate an MPI attribute that
    760:   is attached to a communicator, in this case the attribute is a PetscViewer.
    761: */
    762: PetscMPIInt Petsc_Viewer_Draw_keyval = MPI_KEYVAL_INVALID;

    764: /*@C
    765:     PETSC_VIEWER_DRAW_ - Creates a window PetscViewer shared by all processors
    766:                      in a communicator.

    768:      Collective

    770:      Input Parameter:
    771: .    comm - the MPI communicator to share the window PetscViewer

    773:      Level: intermediate

    775:      Notes:
    776:      Unlike almost all other PETSc routines, PETSC_VIEWER_DRAW_ does not return
    777:      an error code.  The window is usually used in the form
    778: $       XXXView(XXX object,PETSC_VIEWER_DRAW_(comm));

    780: .seealso: PETSC_VIEWER_DRAW_WORLD, PETSC_VIEWER_DRAW_SELF, PetscViewerDrawOpen(),
    781: @*/
    782: PetscViewer  PETSC_VIEWER_DRAW_(MPI_Comm comm)
    783: {
    785:   PetscMPIInt    flag;
    786:   PetscViewer    viewer;
    787:   MPI_Comm       ncomm;

    790:   PetscCommDuplicate(comm,&ncomm,NULL);if (ierr) {PetscError(PETSC_COMM_SELF,__LINE__,"PETSC_VIEWER_DRAW_",__FILE__,PETSC_ERR_PLIB,PETSC_ERROR_INITIAL," ");PetscFunctionReturn(NULL);}
    791:   if (Petsc_Viewer_Draw_keyval == MPI_KEYVAL_INVALID) {
    792:     MPI_Comm_create_keyval(MPI_COMM_NULL_COPY_FN,MPI_COMM_NULL_DELETE_FN,&Petsc_Viewer_Draw_keyval,NULL);
    793:     if (ierr) {PetscError(PETSC_COMM_SELF,__LINE__,"PETSC_VIEWER_DRAW_",__FILE__,PETSC_ERR_PLIB,PETSC_ERROR_INITIAL," ");PetscFunctionReturn(NULL);}
    794:   }
    795:   MPI_Comm_get_attr(ncomm,Petsc_Viewer_Draw_keyval,(void**)&viewer,&flag);
    796:   if (ierr) {PetscError(PETSC_COMM_SELF,__LINE__,"PETSC_VIEWER_DRAW_",__FILE__,PETSC_ERR_PLIB,PETSC_ERROR_INITIAL," ");PetscFunctionReturn(NULL);}
    797:   if (!flag) { /* PetscViewer not yet created */
    798:     PetscViewerDrawOpen(ncomm,NULL,NULL,PETSC_DECIDE,PETSC_DECIDE,300,300,&viewer);
    799:     if (ierr) {PetscError(PETSC_COMM_SELF,__LINE__,"PETSC_VIEWER_DRAW_",__FILE__,PETSC_ERR_PLIB,PETSC_ERROR_REPEAT," ");PetscFunctionReturn(NULL);}
    800:     PetscObjectRegisterDestroy((PetscObject)viewer);
    801:     if (ierr) {PetscError(PETSC_COMM_SELF,__LINE__,"PETSC_VIEWER_DRAW_",__FILE__,PETSC_ERR_PLIB,PETSC_ERROR_REPEAT," ");PetscFunctionReturn(NULL);}
    802:     MPI_Comm_set_attr(ncomm,Petsc_Viewer_Draw_keyval,(void*)viewer);
    803:     if (ierr) {PetscError(PETSC_COMM_SELF,__LINE__,"PETSC_VIEWER_DRAW_",__FILE__,PETSC_ERR_PLIB,PETSC_ERROR_INITIAL," ");PetscFunctionReturn(NULL);}
    804:   }
    805:   PetscCommDestroy(&ncomm);
    806:   if (ierr) {PetscError(PETSC_COMM_SELF,__LINE__,"PETSC_VIEWER_DRAW_",__FILE__,PETSC_ERR_PLIB,PETSC_ERROR_REPEAT," ");PetscFunctionReturn(NULL);}
    807:   PetscFunctionReturn(viewer);
    808: }

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

    813:     Collective on PetscViewer

    815:     Input Parameters:
    816: +   viewer - the PetscViewer (created with PetscViewerDrawOpen())
    817: .   nbounds - number of plots that can be made with this viewer, for example the dof passed to DMDACreate()
    818: -   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, .....

    821:     Options Database:
    822: .   -draw_bounds  minF0,maxF0,minF1,maxF1 - the lower left and upper right bounds

    824:     Level: intermediate

    826:     Notes:
    827:     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
    828:       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
    829:       this viewer. Otherwise the color to physical value meaning changes with each new image if this is not set.

    832: .seealso: PetscViewerDrawGetLG(), PetscViewerDrawGetAxis(), PetscViewerDrawOpen()
    833: @*/
    834: PetscErrorCode  PetscViewerDrawSetBounds(PetscViewer viewer,PetscInt nbounds,const PetscReal *bounds)
    835: {
    836:   PetscViewer_Draw *vdraw;
    837:   PetscBool        isdraw;
    838:   PetscErrorCode   ierr;

    843:   PetscObjectTypeCompare((PetscObject)viewer,PETSCVIEWERDRAW,&isdraw);
    844:   if (!isdraw) return(0);
    845:   vdraw = (PetscViewer_Draw*)viewer->data;

    847:   vdraw->nbounds = nbounds;
    848:   PetscFree(vdraw->bounds);
    849:   PetscMalloc1(2*nbounds,&vdraw->bounds);
    850:   PetscArraycpy(vdraw->bounds,bounds,2*nbounds);
    851:   return(0);
    852: }

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

    857:     Collective on PetscViewer

    859:     Input Parameter:
    860: .   viewer - the PetscViewer (created with PetscViewerDrawOpen())

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

    866:     Level: intermediate

    869: .seealso: PetscViewerDrawGetLG(), PetscViewerDrawGetAxis(), PetscViewerDrawOpen(), PetscViewerDrawSetBounds()
    870: @*/
    871: PetscErrorCode  PetscViewerDrawGetBounds(PetscViewer viewer,PetscInt *nbounds,const PetscReal **bounds)
    872: {
    873:   PetscViewer_Draw *vdraw;
    874:   PetscBool        isdraw;
    875:   PetscErrorCode   ierr;

    879:   PetscObjectTypeCompare((PetscObject)viewer,PETSCVIEWERDRAW,&isdraw);
    880:   if (!isdraw) {if (nbounds) *nbounds = 0; if (bounds) *bounds = NULL; return(0);}
    881:   vdraw = (PetscViewer_Draw*)viewer->data;

    883:   if (nbounds) *nbounds = vdraw->nbounds;
    884:   if (bounds)  *bounds  = vdraw->bounds;
    885:   return(0);
    886: }