PetscErrorCode PetscDrawGetImage_X(PetscDraw draw,unsigned char palette[PETSC_DRAW_MAXCOLOR][3],unsigned int *out_w,unsigned int *out_h,unsigned char *out_pixels[]) { PetscDraw_X *Xwin = (PetscDraw_X*)draw->data; PetscMPIInt rank; PetscErrorCode ierr; PetscFunctionBegin; if (out_w) *out_w = 0; if (out_h) *out_h = 0; if (out_pixels) *out_pixels = NULL; ierr = MPI_Comm_rank(PetscObjectComm((PetscObject)draw),&rank);CHKERRQ(ierr); /* make sure the X server processed requests from all processes */ ierr = PetscDrawCollectiveBegin(draw);CHKERRQ(ierr); XSync(Xwin->disp,True); ierr = PetscDrawCollectiveEnd(draw);CHKERRQ(ierr); ierr = MPI_Barrier(PetscObjectComm((PetscObject)draw));CHKERRQ(ierr); /* only the first process return image data */ ierr = PetscDrawCollectiveBegin(draw);CHKERRQ(ierr); if (!rank) { Window root; XImage *ximage; int pmap[PETSC_DRAW_MAXCOLOR]; unsigned char *pixels = NULL; unsigned int w,h,dummy; int x,y,p; /* copy colormap palette to the caller */ ierr = PetscMemcpy(palette,Xwin->cpalette,sizeof(Xwin->cpalette));CHKERRQ(ierr); /* get image out of the drawable */ XGetGeometry(Xwin->disp,PetscDrawXiDrawable(Xwin),&root,&x,&y,&w,&h,&dummy,&dummy); ximage = XGetImage(Xwin->disp,PetscDrawXiDrawable(Xwin),0,0,w,h,AllPlanes,ZPixmap); if (!ximage) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_PLIB,"Cannot XGetImage()"); /* build indirect sort permutation (a.k.a argsort) of the color -> pixel mapping */ for (p=0; p<PETSC_DRAW_MAXCOLOR; p++) pmap[p] = p; /* identity permutation */ ierr = PetscArgSortPixVal(Xwin->cmapping,pmap,255);CHKERRQ(ierr); /* extract pixel values out of the image and map them to color indices */ ierr = PetscMalloc1(w*h,&pixels);CHKERRQ(ierr); for (p=0,y=0; y<(int)h; y++) for (x=0; x<(int)w; x++) { PetscDrawXiPixVal pix = XGetPixel(ximage,x,y); pixels[p++] = (unsigned char)PetscDrawXiPixelToColor(Xwin,pmap,pix); } XDestroyImage(ximage); *out_w = w; *out_h = h; *out_pixels = pixels; } ierr = PetscDrawCollectiveEnd(draw);CHKERRQ(ierr); PetscFunctionReturn(0); }
/*@ PetscDrawSynchronizedGetMouseButton - Returns location of mouse and which button was pressed. Waits for button to be pressed. Collective over PetscDraw Input Parameter: . draw - the window to be used Output Parameters: + button - one of PETSC_BUTTON_LEFT, PETSC_BUTTON_CENTER, PETSC_BUTTON_RIGHT . x_user, y_user - user coordinates of location (user may pass in NULL). - x_phys, y_phys - window coordinates (user may pass in NULL). Level: intermediate .seealso: PetscDrawGetMouseButton() @*/ PetscErrorCode PetscDrawSynchronizedGetMouseButton(PetscDraw draw,PetscDrawButton *button,PetscReal *x_user,PetscReal *y_user,PetscReal *x_phys,PetscReal *y_phys) { PetscReal bcast[4]; PetscErrorCode ierr; PetscMPIInt rank; PetscFunctionBegin; PetscValidHeaderSpecific(draw,PETSC_DRAW_CLASSID,1); PetscValidPointer(button,2); *button = PETSC_BUTTON_NONE; ierr = MPI_Comm_rank(PetscObjectComm((PetscObject)draw),&rank);CHKERRQ(ierr); ierr = PetscDrawCollectiveBegin(draw);CHKERRQ(ierr); if (!rank) {ierr = PetscDrawGetMouseButton(draw,button,x_user,y_user,x_phys,y_phys);CHKERRQ(ierr);} ierr = PetscDrawCollectiveEnd(draw);CHKERRQ(ierr); ierr = MPI_Bcast((PetscEnum*)button,1,MPIU_ENUM,0,PetscObjectComm((PetscObject)draw));CHKERRQ(ierr); if (x_user) bcast[0] = *x_user; if (y_user) bcast[1] = *y_user; if (x_phys) bcast[2] = *x_phys; if (y_phys) bcast[3] = *y_phys; ierr = MPI_Bcast(bcast,4,MPIU_REAL,0,PetscObjectComm((PetscObject)draw));CHKERRQ(ierr); if (x_user) *x_user = bcast[0]; if (y_user) *y_user = bcast[1]; if (x_phys) *x_phys = bcast[2]; if (y_phys) *y_phys = bcast[3]; PetscFunctionReturn(0); }
/*@C PetscDrawViewPortsCreate - Splits a window into smaller view ports. Each processor shares all the viewports. Collective on PetscDraw Input Parameters: + draw - the drawing context - nports - the number of ports Output Parameter: . ports - a PetscDrawViewPorts context (C structure) Options Database: . -draw_ports - display multiple fields in the same window with PetscDrawPorts instead of in seperate windows Level: advanced Concepts: drawing^in subset of window .seealso: PetscDrawSplitViewPort(), PetscDrawSetViewPort(), PetscDrawViewPortsSet(), PetscDrawViewPortsDestroy() @*/ PetscErrorCode PetscDrawViewPortsCreate(PetscDraw draw,PetscInt nports,PetscDrawViewPorts **newports) { PetscDrawViewPorts *ports; PetscInt i,n; PetscBool isnull; PetscMPIInt rank; PetscReal *xl,*xr,*yl,*yr,h; PetscErrorCode ierr; PetscFunctionBegin; PetscValidHeaderSpecific(draw,PETSC_DRAW_CLASSID,1); if (nports < 1) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_ARG_OUTOFRANGE, "Number of divisions must be positive: %d", nports); PetscValidPointer(newports,3); ierr = PetscDrawIsNull(draw,&isnull);CHKERRQ(ierr); if (isnull) {*newports = NULL; PetscFunctionReturn(0);} ierr = MPI_Comm_rank(PetscObjectComm((PetscObject)draw),&rank);CHKERRQ(ierr); ierr = PetscNew(&ports);CHKERRQ(ierr); *newports = ports; ports->draw = draw; ports->nports = nports; ierr = PetscObjectReference((PetscObject)draw);CHKERRQ(ierr); /* save previous drawport of window */ ierr = PetscDrawGetViewPort(draw,&ports->port_xl,&ports->port_yl,&ports->port_xr,&ports->port_yr);CHKERRQ(ierr); n = (PetscInt)(.1 + PetscSqrtReal((PetscReal)nports)); while (n*n < nports) n++; h = 1.0/n; ierr = PetscMalloc4(n*n,&xl,n*n,&xr,n*n,&yl,n*n,&yr);CHKERRQ(ierr); ports->xl = xl; ports->xr = xr; ports->yl = yl; ports->yr = yr; ierr = PetscDrawSetCoordinates(draw,0.0,0.0,1.0,1.0);CHKERRQ(ierr); ierr = PetscDrawCollectiveBegin(draw);CHKERRQ(ierr); for (i=0; i<n*n; i++) { xl[i] = (i % n)*h; xr[i] = xl[i] + h; yl[i] = (i / n)*h; yr[i] = yl[i] + h; if (!rank) { ierr = PetscDrawLine(draw,xl[i],yl[i],xl[i],yr[i],PETSC_DRAW_BLACK);CHKERRQ(ierr); ierr = PetscDrawLine(draw,xl[i],yr[i],xr[i],yr[i],PETSC_DRAW_BLACK);CHKERRQ(ierr); ierr = PetscDrawLine(draw,xr[i],yr[i],xr[i],yl[i],PETSC_DRAW_BLACK);CHKERRQ(ierr); ierr = PetscDrawLine(draw,xr[i],yl[i],xl[i],yl[i],PETSC_DRAW_BLACK);CHKERRQ(ierr); } xl[i] += .05*h; xr[i] -= .05*h; yl[i] += .05*h; yr[i] -= .05*h; } ierr = PetscDrawCollectiveEnd(draw);CHKERRQ(ierr); ierr = PetscDrawFlush(draw);CHKERRQ(ierr); PetscFunctionReturn(0); }
/*@ PetscDrawScalePopup - draws a contour scale window. Collective on PetscDraw Input Parameters: + popup - the window (often a window obtained via PetscDrawGetPopup() . min - minimum value being plotted - max - maximum value being plotted Level: intermediate Notes: All processors that share the draw MUST call this routine .seealso: PetscDrawGetPopup(), PetscDrawTensorContour() @*/ PetscErrorCode PetscDrawScalePopup(PetscDraw popup,PetscReal min,PetscReal max) { PetscBool isnull; PetscReal xl = 0.0,yl = 0.0,xr = 1.0,yr = 1.0; PetscMPIInt rank; PetscErrorCode ierr; int i; char string[32]; PetscFunctionBegin; if (!popup) PetscFunctionReturn(0); PetscValidHeaderSpecific(popup,PETSC_DRAW_CLASSID,1); ierr = PetscDrawIsNull(popup,&isnull); CHKERRQ(ierr); if (isnull) PetscFunctionReturn(0); ierr = MPI_Comm_rank(PetscObjectComm((PetscObject)popup),&rank); CHKERRQ(ierr); ierr = PetscDrawCheckResizedWindow(popup); CHKERRQ(ierr); ierr = PetscDrawClear(popup); CHKERRQ(ierr); ierr = PetscDrawSetTitle(popup,"Contour Scale"); CHKERRQ(ierr); ierr = PetscDrawSetCoordinates(popup,xl,yl,xr,yr); CHKERRQ(ierr); ierr = PetscDrawCollectiveBegin(popup); CHKERRQ(ierr); if (!rank) { for (i=0; i<10; i++) { int c = PetscDrawRealToColor((PetscReal)i/9,0,1); ierr = PetscDrawRectangle(popup,xl,yl,xr,yr,c,c,c,c); CHKERRQ(ierr); yl += 0.1; } for (i=0; i<10; i++) { PetscReal value = min + i*(max-min)/9; /* look for a value that should be zero, but is not due to round-off */ if (PetscAbsReal(value) < 1.e-10 && max-min > 1.e-6) value = 0.0; ierr = PetscSNPrintf(string,sizeof(string),"%18.16e",(double)value); CHKERRQ(ierr); ierr = PetscDrawString(popup,0.2,0.02+i/10.0,PETSC_DRAW_BLACK,string); CHKERRQ(ierr); } } ierr = PetscDrawCollectiveEnd(popup); CHKERRQ(ierr); ierr = PetscDrawFlush(popup); CHKERRQ(ierr); ierr = PetscDrawSave(popup); CHKERRQ(ierr); PetscFunctionReturn(0); }
/*@ PetscDrawLGSPDraw - Redraws a line graph. Collective on PetscDrawLG Input Parameter: . lg - the line graph context Level: intermediate .seealso: PetscDrawLGDraw(), PetscDrawSPDraw() Developer Notes: This code cheats and uses the fact that the LG and SP structs are the same @*/ PetscErrorCode PetscDrawLGSPDraw(PetscDrawLG lg,PetscDrawSP spin) { PetscDrawLG sp = (PetscDrawLG)spin; PetscReal xmin,xmax,ymin,ymax; PetscErrorCode ierr; PetscBool isnull; PetscMPIInt rank; PetscDraw draw; PetscFunctionBegin; PetscValidHeaderSpecific(lg,PETSC_DRAWLG_CLASSID,1); PetscValidHeaderSpecific(sp,PETSC_DRAWSP_CLASSID,2); ierr = PetscDrawIsNull(lg->win,&isnull);CHKERRQ(ierr); if (isnull) PetscFunctionReturn(0); ierr = MPI_Comm_rank(PetscObjectComm((PetscObject)lg),&rank);CHKERRQ(ierr); draw = lg->win; ierr = PetscDrawCheckResizedWindow(draw);CHKERRQ(ierr); ierr = PetscDrawClear(draw);CHKERRQ(ierr); xmin = PetscMin(lg->xmin,sp->xmin); ymin = PetscMin(lg->ymin,sp->ymin); xmax = PetscMax(lg->xmax,sp->xmax); ymax = PetscMax(lg->ymax,sp->ymax); ierr = PetscDrawAxisSetLimits(lg->axis,xmin,xmax,ymin,ymax);CHKERRQ(ierr); ierr = PetscDrawAxisDraw(lg->axis);CHKERRQ(ierr); ierr = PetscDrawCollectiveBegin(draw);CHKERRQ(ierr); if (!rank) { int i,j,dim,nopts; dim = lg->dim; nopts = lg->nopts; for (i=0; i<dim; i++) { for (j=1; j<nopts; j++) { ierr = PetscDrawLine(draw,lg->x[(j-1)*dim+i],lg->y[(j-1)*dim+i],lg->x[j*dim+i],lg->y[j*dim+i],PETSC_DRAW_BLACK+i);CHKERRQ(ierr); if (lg->use_markers) { ierr = PetscDrawMarker(draw,lg->x[j*dim+i],lg->y[j*dim+i],PETSC_DRAW_RED);CHKERRQ(ierr); } } } dim = sp->dim; nopts = sp->nopts; for (i=0; i<dim; i++) { for (j=0; j<nopts; j++) { ierr = PetscDrawMarker(draw,sp->x[j*dim+i],sp->y[j*dim+i],PETSC_DRAW_RED);CHKERRQ(ierr); } } } ierr = PetscDrawCollectiveEnd(draw);CHKERRQ(ierr); ierr = PetscDrawFlush(draw);CHKERRQ(ierr); ierr = PetscDrawPause(draw);CHKERRQ(ierr); PetscFunctionReturn(0); }
/*@ PetscDrawSplitViewPort - Splits a window shared by several processes into smaller view ports. One for each process. Collective on PetscDraw Input Parameter: . draw - the drawing context Level: advanced Concepts: drawing^in subset of window .seealso: PetscDrawDivideViewPort(), PetscDrawSetViewPort() @*/ PetscErrorCode PetscDrawSplitViewPort(PetscDraw draw) { PetscErrorCode ierr; PetscMPIInt rank,size; PetscInt n; PetscBool isnull; PetscReal xl,xr,yl,yr,h; PetscFunctionBegin; PetscValidHeaderSpecific(draw,PETSC_DRAW_CLASSID,1); ierr = PetscDrawIsNull(draw,&isnull);CHKERRQ(ierr); if (isnull) PetscFunctionReturn(0); ierr = MPI_Comm_rank(PetscObjectComm((PetscObject)draw),&rank);CHKERRQ(ierr); ierr = MPI_Comm_size(PetscObjectComm((PetscObject)draw),&size);CHKERRQ(ierr); n = (PetscInt)(.1 + PetscSqrtReal((PetscReal)size)); while (n*n < size) n++; h = 1.0/n; xl = (rank % n)*h; xr = xl + h; yl = (rank / n)*h; yr = yl + h; ierr = PetscDrawCollectiveBegin(draw);CHKERRQ(ierr); ierr = PetscDrawLine(draw,xl,yl,xl,yr,PETSC_DRAW_BLACK);CHKERRQ(ierr); ierr = PetscDrawLine(draw,xl,yr,xr,yr,PETSC_DRAW_BLACK);CHKERRQ(ierr); ierr = PetscDrawLine(draw,xr,yr,xr,yl,PETSC_DRAW_BLACK);CHKERRQ(ierr); ierr = PetscDrawLine(draw,xr,yl,xl,yl,PETSC_DRAW_BLACK);CHKERRQ(ierr); ierr = PetscDrawCollectiveEnd(draw);CHKERRQ(ierr); ierr = PetscDrawFlush(draw);CHKERRQ(ierr); draw->port_xl = xl + .05*h; draw->port_xr = xr - .05*h; draw->port_yl = yl + .05*h; draw->port_yr = yr - .05*h; if (draw->ops->setviewport) { ierr = (*draw->ops->setviewport)(draw,xl,yl,xr,yr);CHKERRQ(ierr); } PetscFunctionReturn(0); }
/*@C PetscDrawViewPortsCreateRect - Splits a window into smaller view ports. Each processor shares all the viewports. The number of views in the x- and y-directions is specified. Collective on PetscDraw Input Parameters: + draw - the drawing context . nx - the number of x divisions - ny - the number of y divisions Output Parameter: . ports - a PetscDrawViewPorts context (C structure) Level: advanced Concepts: drawing^in subset of window .seealso: PetscDrawSplitViewPort(), PetscDrawSetViewPort(), PetscDrawViewPortsSet(), PetscDrawViewPortsDestroy() @*/ PetscErrorCode PetscDrawViewPortsCreateRect(PetscDraw draw,PetscInt nx,PetscInt ny,PetscDrawViewPorts **newports) { PetscDrawViewPorts *ports; PetscReal *xl,*xr,*yl,*yr,hx,hy; PetscInt i,j,k,n; PetscBool isnull; PetscMPIInt rank; PetscErrorCode ierr; PetscFunctionBegin; PetscValidHeaderSpecific(draw,PETSC_DRAW_CLASSID,1); if ((nx < 1) || (ny < 1)) SETERRQ2(PETSC_COMM_SELF,PETSC_ERR_ARG_OUTOFRANGE, "Number of divisions must be positive: %d x %d", nx, ny); PetscValidPointer(newports,3); ierr = PetscDrawIsNull(draw,&isnull);CHKERRQ(ierr); if (isnull) {*newports = NULL; PetscFunctionReturn(0);} ierr = MPI_Comm_rank(PetscObjectComm((PetscObject)draw),&rank);CHKERRQ(ierr); n = nx*ny; hx = 1.0/nx; hy = 1.0/ny; ierr = PetscNew(&ports);CHKERRQ(ierr); *newports = ports; ports->draw = draw; ports->nports = n; ierr = PetscObjectReference((PetscObject) draw);CHKERRQ(ierr); /* save previous drawport of window */ ierr = PetscDrawGetViewPort(draw,&ports->port_xl,&ports->port_yl,&ports->port_xr,&ports->port_yr);CHKERRQ(ierr); ierr = PetscMalloc4(n,&xl,n,&xr,n,&yl,n,&yr);CHKERRQ(ierr); ports->xr = xr; ports->xl = xl; ports->yl = yl; ports->yr = yr; ierr = PetscDrawSetCoordinates(draw,0.0,0.0,1.0,1.0);CHKERRQ(ierr); ierr = PetscDrawCollectiveBegin(draw);CHKERRQ(ierr); for (i = 0; i < nx; i++) { for (j = 0; j < ny; j++) { k = j*nx+i; xl[k] = i*hx; xr[k] = xl[k] + hx; yl[k] = j*hy; yr[k] = yl[k] + hy; if (!rank) { ierr = PetscDrawLine(draw,xl[k],yl[k],xl[k],yr[k],PETSC_DRAW_BLACK);CHKERRQ(ierr); ierr = PetscDrawLine(draw,xl[k],yr[k],xr[k],yr[k],PETSC_DRAW_BLACK);CHKERRQ(ierr); ierr = PetscDrawLine(draw,xr[k],yr[k],xr[k],yl[k],PETSC_DRAW_BLACK);CHKERRQ(ierr); ierr = PetscDrawLine(draw,xr[k],yl[k],xl[k],yl[k],PETSC_DRAW_BLACK);CHKERRQ(ierr); } xl[k] += .05*hx; xr[k] -= .05*hx; yl[k] += .05*hy; yr[k] -= .05*hy; } } ierr = PetscDrawCollectiveEnd(draw);CHKERRQ(ierr); ierr = PetscDrawFlush(draw);CHKERRQ(ierr); PetscFunctionReturn(0); }
/*@ PetscDrawBarDraw - Redraws a bar graph. Collective on PetscDrawBar Input Parameter: . bar - The bar graph context Level: intermediate .seealso: PetscDrawBar, PetscDrawBarCreate(), PetscDrawBarSetData() @*/ 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; PetscValidHeaderSpecific(bar,PETSC_DRAWBAR_CLASSID,1); ierr = PetscDrawIsNull(bar->win,&isnull);CHKERRQ(ierr); if (isnull) PetscFunctionReturn(0); ierr = MPI_Comm_rank(PetscObjectComm((PetscObject)bar),&rank);CHKERRQ(ierr); if (bar->numBins < 1) PetscFunctionReturn(0); color = bar->color; if (color == PETSC_DRAW_ROTATE) bcolor = PETSC_DRAW_BLACK+1; 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; } } } } draw = bar->win; ierr = PetscDrawCheckResizedWindow(draw);CHKERRQ(ierr); ierr = PetscDrawClear(draw);CHKERRQ(ierr); ierr = PetscDrawAxisSetLimits(bar->axis,xmin,xmax,ymin,ymax);CHKERRQ(ierr); ierr = PetscDrawAxisDraw(bar->axis);CHKERRQ(ierr); ierr = PetscDrawCollectiveBegin(draw);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.5*h,bcolor,labels[idx]);CHKERRQ(ierr); } if (color == PETSC_DRAW_ROTATE) bcolor++; if (bcolor > PETSC_DRAW_BASIC_COLORS-1) bcolor = PETSC_DRAW_BLACK+1; } } ierr = PetscDrawCollectiveEnd(draw);CHKERRQ(ierr); if (bar->sort) {ierr = PetscFree(perm);CHKERRQ(ierr);} ierr = PetscDrawFlush(draw);CHKERRQ(ierr); ierr = PetscDrawPause(draw);CHKERRQ(ierr); PetscFunctionReturn(0); }
/*@ PetscDrawLGDraw - Redraws a line graph. Collective on PetscDrawLG Input Parameter: . lg - the line graph context Level: intermediate .seealso: PetscDrawSPDraw(), PetscDrawLGSPDraw(), PetscDrawLGReset() @*/ PetscErrorCode PetscDrawLGDraw(PetscDrawLG lg) { PetscReal xmin,xmax,ymin,ymax; PetscErrorCode ierr; PetscMPIInt rank; PetscDraw draw; PetscBool isnull; PetscFunctionBegin; PetscValidHeaderSpecific(lg,PETSC_DRAWLG_CLASSID,1); ierr = PetscDrawIsNull(lg->win,&isnull);CHKERRQ(ierr); if (isnull) PetscFunctionReturn(0); ierr = MPI_Comm_rank(PetscObjectComm((PetscObject)lg),&rank);CHKERRQ(ierr); draw = lg->win; ierr = PetscDrawCheckResizedWindow(draw);CHKERRQ(ierr); ierr = PetscDrawClear(draw);CHKERRQ(ierr); xmin = lg->xmin; xmax = lg->xmax; ymin = lg->ymin; ymax = lg->ymax; ierr = PetscDrawAxisSetLimits(lg->axis,xmin,xmax,ymin,ymax);CHKERRQ(ierr); ierr = PetscDrawAxisDraw(lg->axis);CHKERRQ(ierr); ierr = PetscDrawCollectiveBegin(draw);CHKERRQ(ierr); if (!rank) { int i,j,dim=lg->dim,nopts=lg->nopts,cl; for (i=0; i<dim; i++) { for (j=1; j<nopts; j++) { cl = lg->colors ? lg->colors[i] : (PETSC_DRAW_BLACK + i); ierr = PetscDrawLine(draw,lg->x[(j-1)*dim+i],lg->y[(j-1)*dim+i],lg->x[j*dim+i],lg->y[j*dim+i],cl);CHKERRQ(ierr); if (lg->use_markers) {ierr = PetscDrawMarker(draw,lg->x[j*dim+i],lg->y[j*dim+i],cl);CHKERRQ(ierr);} } } } if (!rank && lg->legend) { int i,dim=lg->dim,cl; PetscReal xl,yl,xr,yr,tw,th; size_t slen,len=0; ierr = PetscDrawAxisGetLimits(lg->axis,&xl,&xr,&yl,&yr);CHKERRQ(ierr); ierr = PetscDrawStringGetSize(draw,&tw,&th);CHKERRQ(ierr); for (i=0; i<dim; i++) { ierr = PetscStrlen(lg->legend[i],&slen);CHKERRQ(ierr); len = PetscMax(len,slen); } xr = xr - 1.5*tw; xl = xr - (len + 7)*tw; yr = yr - 1.0*th; yl = yr - (dim + 1)*th; ierr = PetscDrawLine(draw,xl,yl,xr,yl,PETSC_DRAW_BLACK);CHKERRQ(ierr); ierr = PetscDrawLine(draw,xr,yl,xr,yr,PETSC_DRAW_BLACK);CHKERRQ(ierr); ierr = PetscDrawLine(draw,xr,yr,xl,yr,PETSC_DRAW_BLACK);CHKERRQ(ierr); ierr = PetscDrawLine(draw,xl,yr,xl,yl,PETSC_DRAW_BLACK);CHKERRQ(ierr); for (i=0; i<dim; i++) { cl = lg->colors ? lg->colors[i] : (PETSC_DRAW_BLACK + i); ierr = PetscDrawLine(draw,xl + 1*tw,yr - (i + 1)*th,xl + 5*tw,yr - (i + 1)*th,cl);CHKERRQ(ierr); ierr = PetscDrawString(draw,xl + 6*tw,yr - (i + 1.5)*th,PETSC_DRAW_BLACK,lg->legend[i]);CHKERRQ(ierr); } } ierr = PetscDrawCollectiveEnd(draw);CHKERRQ(ierr); ierr = PetscDrawFlush(draw);CHKERRQ(ierr); ierr = PetscDrawPause(draw);CHKERRQ(ierr); PetscFunctionReturn(0); }