Beispiel #1
0
PetscErrorCode PetscDrawDestroy_X(PetscDraw draw)
{
  PetscDraw_X    *win = (PetscDraw_X*)draw->data;
  PetscErrorCode ierr;
#if defined(PETSC_HAVE_POPEN)
  char           command[PETSC_MAX_PATH_LEN];
  PetscMPIInt    rank;
  FILE           *fd;
#endif

  PetscFunctionBegin;
  ierr = PetscDrawSynchronizedClear(draw);CHKERRQ(ierr);

#if defined(PETSC_HAVE_POPEN)
  ierr = MPI_Comm_rank(((PetscObject)draw)->comm,&rank);CHKERRQ(ierr);
  if (draw->savefilename && !rank && draw->savefilemovie) {
    ierr = PetscSNPrintf(command,PETSC_MAX_PATH_LEN,"ffmpeg  -i %s_%%d.Gif %s.m4v",draw->savefilename,draw->savefilename);CHKERRQ(ierr);
    ierr = PetscPOpen(((PetscObject)draw)->comm,PETSC_NULL,command,"r",&fd);CHKERRQ(ierr);
    ierr = PetscPClose(((PetscObject)draw)->comm,fd,PETSC_NULL);CHKERRQ(ierr);
  }
#endif

  XFreeGC(win->disp,win->gc.set);
  XCloseDisplay(win->disp);
  ierr = PetscDrawDestroy(&draw->popup);CHKERRQ(ierr);
  ierr = PetscFree(win->font);CHKERRQ(ierr);
  ierr = PetscFree(win);CHKERRQ(ierr);
  PetscFunctionReturn(0);
}
Beispiel #2
0
PetscErrorCode DMView_DA_1d(DM da,PetscViewer viewer)
{
  PetscErrorCode ierr;
  PetscMPIInt    rank;
  PetscBool      iascii,isdraw,isbinary;
  DM_DA          *dd = (DM_DA*)da->data;
#if defined(PETSC_HAVE_MATLAB_ENGINE)
  PetscBool ismatlab;
#endif

  PetscFunctionBegin;
  ierr = MPI_Comm_rank(PetscObjectComm((PetscObject)da),&rank);CHKERRQ(ierr);

  ierr = PetscObjectTypeCompare((PetscObject)viewer,PETSCVIEWERASCII,&iascii);CHKERRQ(ierr);
  ierr = PetscObjectTypeCompare((PetscObject)viewer,PETSCVIEWERDRAW,&isdraw);CHKERRQ(ierr);
  ierr = PetscObjectTypeCompare((PetscObject)viewer,PETSCVIEWERBINARY,&isbinary);CHKERRQ(ierr);
#if defined(PETSC_HAVE_MATLAB_ENGINE)
  ierr = PetscObjectTypeCompare((PetscObject)viewer,PETSCVIEWERMATLAB,&ismatlab);CHKERRQ(ierr);
#endif
  if (iascii) {
    PetscViewerFormat format;

    ierr = PetscViewerGetFormat(viewer, &format);CHKERRQ(ierr);
    if (format != PETSC_VIEWER_ASCII_VTK && format != PETSC_VIEWER_ASCII_VTK_CELL) {
      DMDALocalInfo info;
      ierr = DMDAGetLocalInfo(da,&info);CHKERRQ(ierr);
      ierr = PetscViewerASCIISynchronizedAllow(viewer,PETSC_TRUE);CHKERRQ(ierr);
      ierr = PetscViewerASCIISynchronizedPrintf(viewer,"Processor [%d] M %D m %D w %D s %D\n",rank,dd->M,dd->m,dd->w,dd->s);CHKERRQ(ierr);
      ierr = PetscViewerASCIISynchronizedPrintf(viewer,"X range of indices: %D %D\n",info.xs,info.xs+info.xm);CHKERRQ(ierr);
      ierr = PetscViewerFlush(viewer);CHKERRQ(ierr);
      ierr = PetscViewerASCIISynchronizedAllow(viewer,PETSC_FALSE);CHKERRQ(ierr);
    } else {
      ierr = DMView_DA_VTK(da, viewer);CHKERRQ(ierr);
    }
  } else if (isdraw) {
    PetscDraw draw;
    double    ymin = -1,ymax = 1,xmin = -1,xmax = dd->M,x;
    PetscInt  base;
    char      node[10];
    PetscBool isnull;

    ierr = PetscViewerDrawGetDraw(viewer,0,&draw);CHKERRQ(ierr);
    ierr = PetscDrawIsNull(draw,&isnull);CHKERRQ(ierr); if (isnull) PetscFunctionReturn(0);

    ierr = PetscDrawSetCoordinates(draw,xmin,ymin,xmax,ymax);CHKERRQ(ierr);
    ierr = PetscDrawSynchronizedClear(draw);CHKERRQ(ierr);

    /* first processor draws all node lines */
    if (!rank) {
      PetscInt xmin_tmp;
      ymin = 0.0; ymax = 0.3;

      for (xmin_tmp=0; xmin_tmp < dd->M; xmin_tmp++) {
        ierr = PetscDrawLine(draw,(double)xmin_tmp,ymin,(double)xmin_tmp,ymax,PETSC_DRAW_BLACK);CHKERRQ(ierr);
      }

      xmin = 0.0; xmax = dd->M - 1;
      ierr = PetscDrawLine(draw,xmin,ymin,xmax,ymin,PETSC_DRAW_BLACK);CHKERRQ(ierr);
      ierr = PetscDrawLine(draw,xmin,ymax,xmax,ymax,PETSC_DRAW_BLACK);CHKERRQ(ierr);
    }

    ierr = PetscDrawSynchronizedFlush(draw);CHKERRQ(ierr);
    ierr = PetscDrawPause(draw);CHKERRQ(ierr);

    /* draw my box */
    ymin = 0; ymax = 0.3; xmin = dd->xs / dd->w; xmax = (dd->xe / dd->w)  - 1;
    ierr = PetscDrawLine(draw,xmin,ymin,xmax,ymin,PETSC_DRAW_RED);CHKERRQ(ierr);
    ierr = PetscDrawLine(draw,xmin,ymin,xmin,ymax,PETSC_DRAW_RED);CHKERRQ(ierr);
    ierr = PetscDrawLine(draw,xmin,ymax,xmax,ymax,PETSC_DRAW_RED);CHKERRQ(ierr);
    ierr = PetscDrawLine(draw,xmax,ymin,xmax,ymax,PETSC_DRAW_RED);CHKERRQ(ierr);

    /* Put in index numbers */
    base = dd->base / dd->w;
    for (x=xmin; x<=xmax; x++) {
      sprintf(node,"%d",(int)base++);
      ierr = PetscDrawString(draw,x,ymin,PETSC_DRAW_RED,node);CHKERRQ(ierr);
    }

    ierr = PetscDrawSynchronizedFlush(draw);CHKERRQ(ierr);
    ierr = PetscDrawPause(draw);CHKERRQ(ierr);
  } else if (isbinary) {
    ierr = DMView_DA_Binary(da,viewer);CHKERRQ(ierr);
#if defined(PETSC_HAVE_MATLAB_ENGINE)
  } else if (ismatlab) {
    ierr = DMView_DA_Matlab(da,viewer);CHKERRQ(ierr);
#endif
  }
  PetscFunctionReturn(0);
}
Beispiel #3
0
PetscErrorCode VecView_MPI_Draw_DA1d(Vec xin,PetscViewer v)
{
  DM                da;
  PetscErrorCode    ierr;
  PetscMPIInt       rank,size,tag1,tag2;
  PetscInt          i,n,N,step,istart,isize,j,nbounds;
  MPI_Status        status;
  PetscReal         coors[4],ymin,ymax,min,max,xmin = 0.0,xmax = 0.0,tmp = 0.0,xgtmp = 0.0;
  const PetscScalar *array,*xg;
  PetscDraw         draw;
  PetscBool         isnull,showpoints = PETSC_FALSE;
  MPI_Comm          comm;
  PetscDrawAxis     axis;
  Vec               xcoor;
  DMBoundaryType    bx;
  const PetscReal   *bounds;
  PetscInt          *displayfields;
  PetscInt          k,ndisplayfields;
  PetscBool         hold;

  PetscFunctionBegin;
  ierr = PetscViewerDrawGetDraw(v,0,&draw);CHKERRQ(ierr);
  ierr = PetscDrawIsNull(draw,&isnull);CHKERRQ(ierr); if (isnull) PetscFunctionReturn(0);
  ierr = PetscViewerDrawGetBounds(v,&nbounds,&bounds);CHKERRQ(ierr);

  ierr = VecGetDM(xin,&da);CHKERRQ(ierr);
  if (!da) SETERRQ(PetscObjectComm((PetscObject)xin),PETSC_ERR_ARG_WRONG,"Vector not generated from a DMDA");

  ierr = PetscOptionsGetBool(NULL,"-draw_vec_mark_points",&showpoints,NULL);CHKERRQ(ierr);

  ierr = DMDAGetInfo(da,0,&N,0,0,0,0,0,&step,0,&bx,0,0,0);CHKERRQ(ierr);
  ierr = DMDAGetCorners(da,&istart,0,0,&isize,0,0);CHKERRQ(ierr);
  ierr = VecGetArrayRead(xin,&array);CHKERRQ(ierr);
  ierr = VecGetLocalSize(xin,&n);CHKERRQ(ierr);
  n    = n/step;

  /* get coordinates of nodes */
  ierr = DMGetCoordinates(da,&xcoor);CHKERRQ(ierr);
  if (!xcoor) {
    ierr = DMDASetUniformCoordinates(da,0.0,1.0,0.0,0.0,0.0,0.0);CHKERRQ(ierr);
    ierr = DMGetCoordinates(da,&xcoor);CHKERRQ(ierr);
  }
  ierr = VecGetArrayRead(xcoor,&xg);CHKERRQ(ierr);

  ierr = PetscObjectGetComm((PetscObject)xin,&comm);CHKERRQ(ierr);
  ierr = MPI_Comm_size(comm,&size);CHKERRQ(ierr);
  ierr = MPI_Comm_rank(comm,&rank);CHKERRQ(ierr);

  /*
      Determine the min and max x coordinate in plot
  */
  if (!rank) {
    xmin = PetscRealPart(xg[0]);
  }
  if (rank == size-1) {
    xmax = PetscRealPart(xg[n-1]);
  }
  ierr = MPI_Bcast(&xmin,1,MPIU_REAL,0,comm);CHKERRQ(ierr);
  ierr = MPI_Bcast(&xmax,1,MPIU_REAL,size-1,comm);CHKERRQ(ierr);

  ierr = DMDASelectFields(da,&ndisplayfields,&displayfields);CHKERRQ(ierr);
  for (k=0; k<ndisplayfields; k++) {
    j    = displayfields[k];
    ierr = PetscViewerDrawGetDraw(v,k,&draw);CHKERRQ(ierr);
    ierr = PetscDrawCheckResizedWindow(draw);CHKERRQ(ierr);

    /*
        Determine the min and max y coordinate in plot
    */
    min = 1.e20; max = -1.e20;
    for (i=0; i<n; i++) {
      if (PetscRealPart(array[j+i*step]) < min) min = PetscRealPart(array[j+i*step]);
      if (PetscRealPart(array[j+i*step]) > max) max = PetscRealPart(array[j+i*step]);
    }
    if (min + 1.e-10 > max) {
      min -= 1.e-5;
      max += 1.e-5;
    }
    if (j < nbounds) {
      min = PetscMin(min,bounds[2*j]);
      max = PetscMax(max,bounds[2*j+1]);
    }

    ierr = MPI_Reduce(&min,&ymin,1,MPIU_REAL,MPIU_MIN,0,comm);CHKERRQ(ierr);
    ierr = MPI_Reduce(&max,&ymax,1,MPIU_REAL,MPIU_MAX,0,comm);CHKERRQ(ierr);

    ierr = PetscViewerDrawGetHold(v,&hold);CHKERRQ(ierr);
    if (!hold) {
      ierr = PetscDrawSynchronizedClear(draw);CHKERRQ(ierr);
    }
    ierr = PetscViewerDrawGetDrawAxis(v,k,&axis);CHKERRQ(ierr);
    ierr = PetscLogObjectParent((PetscObject)draw,(PetscObject)axis);CHKERRQ(ierr);
    if (!rank) {
      const char *title;

      ierr = PetscDrawAxisSetLimits(axis,xmin,xmax,ymin,ymax);CHKERRQ(ierr);
      ierr = PetscDrawAxisDraw(axis);CHKERRQ(ierr);
      ierr = PetscDrawGetCoordinates(draw,coors,coors+1,coors+2,coors+3);CHKERRQ(ierr);
      ierr = DMDAGetFieldName(da,j,&title);CHKERRQ(ierr);
      if (title) {ierr = PetscDrawSetTitle(draw,title);CHKERRQ(ierr);}
    }
    ierr = MPI_Bcast(coors,4,MPIU_REAL,0,comm);CHKERRQ(ierr);
    if (rank) {
      ierr = PetscDrawSetCoordinates(draw,coors[0],coors[1],coors[2],coors[3]);CHKERRQ(ierr);
    }

    /* draw local part of vector */
    ierr = PetscObjectGetNewTag((PetscObject)xin,&tag1);CHKERRQ(ierr);
    ierr = PetscObjectGetNewTag((PetscObject)xin,&tag2);CHKERRQ(ierr);
    if (rank < size-1) { /*send value to right */
      ierr = MPI_Send((void*)&array[j+(n-1)*step],1,MPIU_REAL,rank+1,tag1,comm);CHKERRQ(ierr);
      ierr = MPI_Send((void*)&xg[n-1],1,MPIU_REAL,rank+1,tag1,comm);CHKERRQ(ierr);
    }
    if (!rank && bx == DM_BOUNDARY_PERIODIC && size > 1) { /* first processor sends first value to last */
      ierr = MPI_Send((void*)&array[j],1,MPIU_REAL,size-1,tag2,comm);CHKERRQ(ierr);
    }

    for (i=1; i<n; i++) {
      ierr = PetscDrawLine(draw,PetscRealPart(xg[i-1]),PetscRealPart(array[j+step*(i-1)]),PetscRealPart(xg[i]),PetscRealPart(array[j+step*i]),PETSC_DRAW_RED);CHKERRQ(ierr);
      if (showpoints) {
        ierr = PetscDrawPoint(draw,PetscRealPart(xg[i-1]),PetscRealPart(array[j+step*(i-1)]),PETSC_DRAW_BLACK);CHKERRQ(ierr);
      }
    }
    if (rank) { /* receive value from left */
      ierr = MPI_Recv(&tmp,1,MPIU_REAL,rank-1,tag1,comm,&status);CHKERRQ(ierr);
      ierr = MPI_Recv(&xgtmp,1,MPIU_REAL,rank-1,tag1,comm,&status);CHKERRQ(ierr);
      ierr = PetscDrawLine(draw,xgtmp,tmp,PetscRealPart(xg[0]),PetscRealPart(array[j]),PETSC_DRAW_RED);CHKERRQ(ierr);
      if (showpoints) {
        ierr = PetscDrawPoint(draw,xgtmp,tmp,PETSC_DRAW_BLACK);CHKERRQ(ierr);
      }
    }
    if (rank == size-1 && bx == DM_BOUNDARY_PERIODIC && size > 1) {
      ierr = MPI_Recv(&tmp,1,MPIU_REAL,0,tag2,comm,&status);CHKERRQ(ierr);
      /* If the mesh is not uniform we do not know the mesh spacing between the last point on the right and the first ghost point */
      ierr = PetscDrawLine(draw,PetscRealPart(xg[n-1]),PetscRealPart(array[j+step*(n-1)]),PetscRealPart(xg[n-1]+(xg[n-1]-xg[n-2])),tmp,PETSC_DRAW_RED);CHKERRQ(ierr);
      if (showpoints) {
        ierr = PetscDrawPoint(draw,PetscRealPart(xg[n-2]),PetscRealPart(array[j+step*(n-1)]),PETSC_DRAW_BLACK);CHKERRQ(ierr);
      }
    }
    ierr = PetscDrawSynchronizedFlush(draw);CHKERRQ(ierr);
    ierr = PetscDrawPause(draw);CHKERRQ(ierr);
  }
  ierr = PetscFree(displayfields);CHKERRQ(ierr);
  ierr = VecRestoreArrayRead(xcoor,&xg);CHKERRQ(ierr);
  ierr = VecRestoreArrayRead(xin,&array);CHKERRQ(ierr);
  PetscFunctionReturn(0);
}
Beispiel #4
0
PetscErrorCode DMView_DA_2d(DM da,PetscViewer viewer)
{
    PetscErrorCode ierr;
    PetscMPIInt    rank;
    PetscBool      iascii,isdraw,isbinary;
    DM_DA          *dd = (DM_DA*)da->data;
#if defined(PETSC_HAVE_MATLAB_ENGINE)
    PetscBool ismatlab;
#endif

    PetscFunctionBegin;
    ierr = MPI_Comm_rank(PetscObjectComm((PetscObject)da),&rank);
    CHKERRQ(ierr);

    ierr = PetscObjectTypeCompare((PetscObject)viewer,PETSCVIEWERASCII,&iascii);
    CHKERRQ(ierr);
    ierr = PetscObjectTypeCompare((PetscObject)viewer,PETSCVIEWERDRAW,&isdraw);
    CHKERRQ(ierr);
    ierr = PetscObjectTypeCompare((PetscObject)viewer,PETSCVIEWERBINARY,&isbinary);
    CHKERRQ(ierr);
#if defined(PETSC_HAVE_MATLAB_ENGINE)
    ierr = PetscObjectTypeCompare((PetscObject)viewer,PETSCVIEWERMATLAB,&ismatlab);
    CHKERRQ(ierr);
#endif
    if (iascii) {
        PetscViewerFormat format;

        ierr = PetscViewerGetFormat(viewer, &format);
        CHKERRQ(ierr);
        if (format != PETSC_VIEWER_ASCII_VTK && format != PETSC_VIEWER_ASCII_VTK_CELL) {
            DMDALocalInfo info;
            ierr = DMDAGetLocalInfo(da,&info);
            CHKERRQ(ierr);
            ierr = PetscViewerASCIISynchronizedAllow(viewer,PETSC_TRUE);
            CHKERRQ(ierr);
            ierr = PetscViewerASCIISynchronizedPrintf(viewer,"Processor [%d] M %D N %D m %D n %D w %D s %D\n",rank,dd->M,dd->N,dd->m,dd->n,dd->w,dd->s);
            CHKERRQ(ierr);
            ierr = PetscViewerASCIISynchronizedPrintf(viewer,"X range of indices: %D %D, Y range of indices: %D %D\n",info.xs,info.xs+info.xm,info.ys,info.ys+info.ym);
            CHKERRQ(ierr);
            ierr = PetscViewerFlush(viewer);
            CHKERRQ(ierr);
            ierr = PetscViewerASCIISynchronizedAllow(viewer,PETSC_FALSE);
            CHKERRQ(ierr);
        } else {
            ierr = DMView_DA_VTK(da,viewer);
            CHKERRQ(ierr);
        }
    } else if (isdraw) {
        PetscDraw draw;
        double    ymin = -1*dd->s-1,ymax = dd->N+dd->s;
        double    xmin = -1*dd->s-1,xmax = dd->M+dd->s;
        double    x,y;
        PetscInt  base,*idx;
        char      node[10];
        PetscBool isnull;

        ierr = PetscViewerDrawGetDraw(viewer,0,&draw);
        CHKERRQ(ierr);
        ierr = PetscDrawIsNull(draw,&isnull);
        CHKERRQ(ierr);
        if (isnull) PetscFunctionReturn(0);
        if (!da->coordinates) {
            ierr = PetscDrawSetCoordinates(draw,xmin,ymin,xmax,ymax);
            CHKERRQ(ierr);
        }
        ierr = PetscDrawSynchronizedClear(draw);
        CHKERRQ(ierr);

        /* first processor draw all node lines */
        if (!rank) {
            ymin = 0.0;
            ymax = dd->N - 1;
            for (xmin=0; xmin<dd->M; xmin++) {
                ierr = PetscDrawLine(draw,xmin,ymin,xmin,ymax,PETSC_DRAW_BLACK);
                CHKERRQ(ierr);
            }
            xmin = 0.0;
            xmax = dd->M - 1;
            for (ymin=0; ymin<dd->N; ymin++) {
                ierr = PetscDrawLine(draw,xmin,ymin,xmax,ymin,PETSC_DRAW_BLACK);
                CHKERRQ(ierr);
            }
        }
        ierr = PetscDrawSynchronizedFlush(draw);
        CHKERRQ(ierr);
        ierr = PetscDrawPause(draw);
        CHKERRQ(ierr);

        /* draw my box */
        ymin = dd->ys;
        ymax = dd->ye - 1;
        xmin = dd->xs/dd->w;
        xmax =(dd->xe-1)/dd->w;
        ierr = PetscDrawLine(draw,xmin,ymin,xmax,ymin,PETSC_DRAW_RED);
        CHKERRQ(ierr);
        ierr = PetscDrawLine(draw,xmin,ymin,xmin,ymax,PETSC_DRAW_RED);
        CHKERRQ(ierr);
        ierr = PetscDrawLine(draw,xmin,ymax,xmax,ymax,PETSC_DRAW_RED);
        CHKERRQ(ierr);
        ierr = PetscDrawLine(draw,xmax,ymin,xmax,ymax,PETSC_DRAW_RED);
        CHKERRQ(ierr);

        /* put in numbers */
        base = (dd->base)/dd->w;
        for (y=ymin; y<=ymax; y++) {
            for (x=xmin; x<=xmax; x++) {
                sprintf(node,"%d",(int)base++);
                ierr = PetscDrawString(draw,x,y,PETSC_DRAW_BLACK,node);
                CHKERRQ(ierr);
            }
        }

        ierr = PetscDrawSynchronizedFlush(draw);
        CHKERRQ(ierr);
        ierr = PetscDrawPause(draw);
        CHKERRQ(ierr);
        /* overlay ghost numbers, useful for error checking */
        /* put in numbers */

        base = 0;
        idx = dd->idx;
        ymin = dd->Ys;
        ymax = dd->Ye;
        xmin = dd->Xs;
        xmax = dd->Xe;
        for (y=ymin; y<ymax; y++) {
            for (x=xmin; x<xmax; x++) {
                if ((base % dd->w) == 0) {
                    sprintf(node,"%d",(int)(idx[base]/dd->w));
                    ierr = PetscDrawString(draw,x/dd->w,y,PETSC_DRAW_BLUE,node);
                    CHKERRQ(ierr);
                }
                base++;
            }
        }
        ierr = PetscDrawSynchronizedFlush(draw);
        CHKERRQ(ierr);
        ierr = PetscDrawPause(draw);
        CHKERRQ(ierr);
    } else if (isbinary) {
        ierr = DMView_DA_Binary(da,viewer);
        CHKERRQ(ierr);
#if defined(PETSC_HAVE_MATLAB_ENGINE)
    } else if (ismatlab) {
        ierr = DMView_DA_Matlab(da,viewer);
        CHKERRQ(ierr);
#endif
    }
    PetscFunctionReturn(0);
}
Beispiel #5
0
/*@
  PetscDrawBarDraw - Redraws a bar graph.

  Collective, but ignored by all processors except processor 0 in PetscDrawBar

  Input Parameter:
. bar - The bar graph context

  Level: intermediate

@*/
PetscErrorCode  PetscDrawBarDraw(PetscDrawBar bar)
{
    PetscDraw      draw;
    PetscBool      isnull;
    PetscReal      xmin,xmax,ymin,ymax,*values,binLeft,binRight;
    PetscInt       numValues,i,bcolor,color,idx,*perm,nplot;
    PetscMPIInt    rank;
    PetscErrorCode ierr;
    char           **labels;

    PetscFunctionBegin;
    if (!bar) PetscFunctionReturn(0);
    PetscValidHeaderSpecific(bar,PETSC_DRAWBAR_CLASSID,1);

    draw = bar->win;
    ierr = PetscDrawIsNull(draw,&isnull);
    CHKERRQ(ierr);
    if (isnull) PetscFunctionReturn(0);
    if (bar->numBins < 1) PetscFunctionReturn(0);
    ierr = MPI_Comm_rank(PetscObjectComm((PetscObject)bar),&rank);
    CHKERRQ(ierr);

    color = bar->color;
    if (color == PETSC_DRAW_ROTATE) bcolor = 2;
    else bcolor = color;

    numValues = bar->numBins;
    values    = bar->values;
    if (bar->ymin == bar->ymax) {
        /* user has not set bounds on bars so set them based on the data */
        ymin = PETSC_MAX_REAL;
        ymax = PETSC_MIN_REAL;
        for (i=0; i<numValues; i++) {
            ymin = PetscMin(ymin,values[i]);
            ymax = PetscMax(ymax,values[i]);
        }
    } else {
        ymin      = bar->ymin;
        ymax      = bar->ymax;
    }
    nplot  = numValues;  /* number of points to actually plot; if some are lower than requested tolerance */
    xmin   = 0.0;
    xmax   = nplot;
    labels = bar->labels;

    if (bar->sort) {
        ierr = PetscMalloc1(numValues,&perm);
        CHKERRQ(ierr);
        for (i=0; i<numValues; i++) perm[i] = i;
        ierr = PetscSortRealWithPermutation(numValues,values,perm);
        CHKERRQ(ierr);
        if (bar->sorttolerance) {
            for (i=0; i<numValues; i++) {
                if (values[perm[numValues - i - 1]] < bar->sorttolerance) {
                    nplot = i;
                    break;
                }
            }
        }
    }

    ierr = PetscDrawCheckResizedWindow(draw);
    CHKERRQ(ierr);
    ierr = PetscDrawSynchronizedClear(draw);
    CHKERRQ(ierr);
    ierr = PetscDrawCollectiveBegin(draw);
    CHKERRQ(ierr);

    ierr = PetscDrawAxisSetLimits(bar->axis,xmin,xmax,ymin,ymax);
    CHKERRQ(ierr);
    ierr = PetscDrawAxisDraw(bar->axis);
    CHKERRQ(ierr);

    if (!rank) { /* Draw bins */
        for (i=0; i<nplot; i++) {
            idx = (bar->sort ? perm[numValues - i - 1] : i);
            binLeft  = xmin + i;
            binRight = xmin + i + 1;
            ierr = PetscDrawRectangle(draw,binLeft,ymin,binRight,values[idx],bcolor,bcolor,bcolor,bcolor);
            CHKERRQ(ierr);
            ierr = PetscDrawLine(draw,binLeft,ymin,binLeft,values[idx],PETSC_DRAW_BLACK);
            CHKERRQ(ierr);
            ierr = PetscDrawLine(draw,binRight,ymin,binRight,values[idx],PETSC_DRAW_BLACK);
            CHKERRQ(ierr);
            ierr = PetscDrawLine(draw,binLeft,values[idx],binRight,values[idx],PETSC_DRAW_BLACK);
            CHKERRQ(ierr);
            if (labels) {
                PetscReal h;
                ierr = PetscDrawStringGetSize(draw,NULL,&h);
                CHKERRQ(ierr);
                ierr = PetscDrawStringCentered(draw,.5*(binLeft+binRight),ymin - 1.2*h,bcolor,labels[idx]);
                CHKERRQ(ierr);
            }
            if (color == PETSC_DRAW_ROTATE) bcolor++;
            if (bcolor > PETSC_DRAW_BASIC_COLORS-1) bcolor = 2;
        }
    }
    if (bar->sort) {
        ierr = PetscFree(perm);
        CHKERRQ(ierr);
    }

    ierr = PetscDrawCollectiveEnd(draw);
    CHKERRQ(ierr);
    ierr = PetscDrawSynchronizedFlush(draw);
    CHKERRQ(ierr);
    ierr = PetscDrawPause(draw);
    CHKERRQ(ierr);
    PetscFunctionReturn(0);
}