1 2 /* 3 Contains the data structure for drawing scatter plots 4 graphs in a window with an axis. This is intended for scatter 5 plots that change dynamically. 6 */ 7 8 #include <petscdraw.h> /*I "petscdraw.h" I*/ 9 #include <petsc/private/petscimpl.h> /*I "petscsys.h" I*/ 10 11 PetscClassId PETSC_DRAWSP_CLASSID = 0; 12 13 struct _p_PetscDrawSP { 14 PETSCHEADER(int); 15 PetscErrorCode (*destroy)(PetscDrawSP); 16 PetscErrorCode (*view)(PetscDrawSP,PetscViewer); 17 int len,loc; 18 PetscDraw win; 19 PetscDrawAxis axis; 20 PetscReal xmin,xmax,ymin,ymax,*x,*y; 21 int nopts,dim; 22 }; 23 24 #define CHUNCKSIZE 100 25 26 /*@C 27 PetscDrawSPCreate - Creates a scatter plot data structure. 28 29 Collective on PetscDraw 30 31 Input Parameters: 32 + win - the window where the graph will be made. 33 - dim - the number of sets of points which will be drawn 34 35 Output Parameters: 36 . drawsp - the scatter plot context 37 38 Level: intermediate 39 40 Notes: 41 Add points to the plot with PetscDrawSPAddPoint() or PetscDrawSPAddPoints(); the new points are not displayed until PetscDrawSPDraw() is called. 42 43 PetscDrawSPReset() removes all the points that have been added 44 45 The MPI communicator that owns the PetscDraw owns this PetscDrawSP, but the calls to set options and add points are ignored on all processes except the 46 zeroth MPI process in the communicator. All MPI processes in the communicator must call PetscDrawSPDraw() to display the updated graph. 47 48 .seealso: PetscDrawLGCreate(), PetscDrawLG, PetscDrawBarCreate(), PetscDrawBar, PetscDrawHGCreate(), PetscDrawHG, PetscDrawSPDestroy(), PetscDraw, PetscDrawSP, PetscDrawSPSetDimension(), PetscDrawSPReset(), 49 PetscDrawSPAddPoint(), PetscDrawSPAddPoints(), PetscDrawSPDraw(), PetscDrawSPSave(), PetscDrawSPSetLimits(), PetscDrawSPGetAxis(),PetscDrawAxis, PetscDrawSPGetDraw() 50 @*/ 51 PetscErrorCode PetscDrawSPCreate(PetscDraw draw,int dim,PetscDrawSP *drawsp) 52 { 53 PetscDrawSP sp; 54 PetscErrorCode ierr; 55 56 PetscFunctionBegin; 57 PetscValidHeaderSpecific(draw,PETSC_DRAW_CLASSID,1); 58 PetscValidLogicalCollectiveInt(draw,dim,2); 59 PetscValidPointer(drawsp,3); 60 61 ierr = PetscHeaderCreate(sp,PETSC_DRAWSP_CLASSID,"DrawSP","Scatter Plot","Draw",PetscObjectComm((PetscObject)draw),PetscDrawSPDestroy,NULL);CHKERRQ(ierr); 62 ierr = PetscLogObjectParent((PetscObject)draw,(PetscObject)sp);CHKERRQ(ierr); 63 64 ierr = PetscObjectReference((PetscObject)draw);CHKERRQ(ierr); 65 sp->win = draw; 66 67 sp->view = NULL; 68 sp->destroy = NULL; 69 sp->nopts = 0; 70 sp->dim = dim; 71 sp->xmin = 1.e20; 72 sp->ymin = 1.e20; 73 sp->xmax = -1.e20; 74 sp->ymax = -1.e20; 75 76 ierr = PetscMalloc2(dim*CHUNCKSIZE,&sp->x,dim*CHUNCKSIZE,&sp->y);CHKERRQ(ierr); 77 ierr = PetscLogObjectMemory((PetscObject)sp,2*dim*CHUNCKSIZE*sizeof(PetscReal));CHKERRQ(ierr); 78 79 sp->len = dim*CHUNCKSIZE; 80 sp->loc = 0; 81 82 ierr = PetscDrawAxisCreate(draw,&sp->axis);CHKERRQ(ierr); 83 ierr = PetscLogObjectParent((PetscObject)sp,(PetscObject)sp->axis);CHKERRQ(ierr); 84 85 *drawsp = sp; 86 PetscFunctionReturn(0); 87 } 88 89 /*@ 90 PetscDrawSPSetDimension - Change the number of sets of points that are to be drawn. 91 92 Logically Collective on PetscDrawSP 93 94 Input Parameter: 95 + sp - the line graph context. 96 - dim - the number of curves. 97 98 Level: intermediate 99 100 .seealso: PetscDrawSP, PetscDrawSPCreate(), PetscDrawSPAddPoint(), PetscDrawSPAddPoints() 101 102 @*/ 103 PetscErrorCode PetscDrawSPSetDimension(PetscDrawSP sp,int dim) 104 { 105 PetscErrorCode ierr; 106 107 PetscFunctionBegin; 108 PetscValidHeaderSpecific(sp,PETSC_DRAWSP_CLASSID,1); 109 PetscValidLogicalCollectiveInt(sp,dim,2); 110 if (sp->dim == dim) PetscFunctionReturn(0); 111 112 ierr = PetscFree2(sp->x,sp->y);CHKERRQ(ierr); 113 sp->dim = dim; 114 ierr = PetscMalloc2(dim*CHUNCKSIZE,&sp->x,dim*CHUNCKSIZE,&sp->y);CHKERRQ(ierr); 115 ierr = PetscLogObjectMemory((PetscObject)sp,2*dim*CHUNCKSIZE*sizeof(PetscReal));CHKERRQ(ierr); 116 sp->len = dim*CHUNCKSIZE; 117 PetscFunctionReturn(0); 118 } 119 120 /*@ 121 PetscDrawSPReset - Clears line graph to allow for reuse with new data. 122 123 Logically Collective on PetscDrawSP 124 125 Input Parameter: 126 . sp - the line graph context. 127 128 Level: intermediate 129 130 .seealso: PetscDrawSP, PetscDrawSPCreate(), PetscDrawSPAddPoint(), PetscDrawSPAddPoints(), PetscDrawSPDraw() 131 @*/ 132 PetscErrorCode PetscDrawSPReset(PetscDrawSP sp) 133 { 134 PetscFunctionBegin; 135 PetscValidHeaderSpecific(sp,PETSC_DRAWSP_CLASSID,1); 136 sp->xmin = 1.e20; 137 sp->ymin = 1.e20; 138 sp->xmax = -1.e20; 139 sp->ymax = -1.e20; 140 sp->loc = 0; 141 sp->nopts = 0; 142 PetscFunctionReturn(0); 143 } 144 145 /*@C 146 PetscDrawSPDestroy - Frees all space taken up by scatter plot data structure. 147 148 Collective on PetscDrawSP 149 150 Input Parameter: 151 . sp - the line graph context 152 153 Level: intermediate 154 155 .seealso: PetscDrawSPCreate(), PetscDrawSP, PetscDrawSPReset() 156 157 @*/ 158 PetscErrorCode PetscDrawSPDestroy(PetscDrawSP *sp) 159 { 160 PetscErrorCode ierr; 161 162 PetscFunctionBegin; 163 if (!*sp) PetscFunctionReturn(0); 164 PetscValidHeaderSpecific(*sp,PETSC_DRAWSP_CLASSID,1); 165 if (--((PetscObject)(*sp))->refct > 0) {*sp = NULL; PetscFunctionReturn(0);} 166 167 ierr = PetscFree2((*sp)->x,(*sp)->y);CHKERRQ(ierr); 168 ierr = PetscDrawAxisDestroy(&(*sp)->axis);CHKERRQ(ierr); 169 ierr = PetscDrawDestroy(&(*sp)->win);CHKERRQ(ierr); 170 ierr = PetscHeaderDestroy(sp);CHKERRQ(ierr); 171 PetscFunctionReturn(0); 172 } 173 174 /*@ 175 PetscDrawSPAddPoint - Adds another point to each of the scatter plots. 176 177 Logically Collective on PetscDrawSP 178 179 Input Parameters: 180 + sp - the scatter plot data structure 181 - x, y - the points to two vectors containing the new x and y 182 point for each curve. 183 184 Level: intermediate 185 186 Notes: 187 the new points will not be displayed until a call to PetscDrawSPDraw() is made 188 189 .seealso: PetscDrawSPAddPoints(), PetscDrawSP, PetscDrawSPCreate(), PetscDrawSPReset(), PetscDrawSPDraw() 190 191 @*/ 192 PetscErrorCode PetscDrawSPAddPoint(PetscDrawSP sp,PetscReal *x,PetscReal *y) 193 { 194 PetscErrorCode ierr; 195 PetscInt i; 196 197 PetscFunctionBegin; 198 PetscValidHeaderSpecific(sp,PETSC_DRAWSP_CLASSID,1); 199 200 if (sp->loc+sp->dim >= sp->len) { /* allocate more space */ 201 PetscReal *tmpx,*tmpy; 202 ierr = PetscMalloc2(sp->len+sp->dim*CHUNCKSIZE,&tmpx,sp->len+sp->dim*CHUNCKSIZE,&tmpy);CHKERRQ(ierr); 203 ierr = PetscLogObjectMemory((PetscObject)sp,2*sp->dim*CHUNCKSIZE*sizeof(PetscReal));CHKERRQ(ierr); 204 ierr = PetscArraycpy(tmpx,sp->x,sp->len);CHKERRQ(ierr); 205 ierr = PetscArraycpy(tmpy,sp->y,sp->len);CHKERRQ(ierr); 206 ierr = PetscFree2(sp->x,sp->y);CHKERRQ(ierr); 207 sp->x = tmpx; 208 sp->y = tmpy; 209 sp->len += sp->dim*CHUNCKSIZE; 210 } 211 for (i=0; i<sp->dim; i++) { 212 if (x[i] > sp->xmax) sp->xmax = x[i]; 213 if (x[i] < sp->xmin) sp->xmin = x[i]; 214 if (y[i] > sp->ymax) sp->ymax = y[i]; 215 if (y[i] < sp->ymin) sp->ymin = y[i]; 216 217 sp->x[sp->loc] = x[i]; 218 sp->y[sp->loc++] = y[i]; 219 } 220 sp->nopts++; 221 PetscFunctionReturn(0); 222 } 223 224 225 /*@C 226 PetscDrawSPAddPoints - Adds several points to each of the scatter plots. 227 228 Logically Collective on PetscDrawSP 229 230 Input Parameters: 231 + sp - the LineGraph data structure 232 . xx,yy - points to two arrays of pointers that point to arrays 233 containing the new x and y points for each curve. 234 - n - number of points being added 235 236 Level: intermediate 237 238 Notes: 239 the new points will not be displayed until a call to PetscDrawSPDraw() is made 240 241 .seealso: PetscDrawSPAddPoint(), PetscDrawSP, PetscDrawSPCreate(), PetscDrawSPReset(), PetscDrawSPDraw() 242 @*/ 243 PetscErrorCode PetscDrawSPAddPoints(PetscDrawSP sp,int n,PetscReal **xx,PetscReal **yy) 244 { 245 PetscErrorCode ierr; 246 PetscInt i,j,k; 247 PetscReal *x,*y; 248 249 PetscFunctionBegin; 250 PetscValidHeaderSpecific(sp,PETSC_DRAWSP_CLASSID,1); 251 252 if (sp->loc+n*sp->dim >= sp->len) { /* allocate more space */ 253 PetscReal *tmpx,*tmpy; 254 PetscInt chunk = CHUNCKSIZE; 255 if (n > chunk) chunk = n; 256 ierr = PetscMalloc2(sp->len+sp->dim*chunk,&tmpx,sp->len+sp->dim*chunk,&tmpy);CHKERRQ(ierr); 257 ierr = PetscLogObjectMemory((PetscObject)sp,2*sp->dim*CHUNCKSIZE*sizeof(PetscReal));CHKERRQ(ierr); 258 ierr = PetscArraycpy(tmpx,sp->x,sp->len);CHKERRQ(ierr); 259 ierr = PetscArraycpy(tmpy,sp->y,sp->len);CHKERRQ(ierr); 260 ierr = PetscFree2(sp->x,sp->y);CHKERRQ(ierr); 261 262 sp->x = tmpx; 263 sp->y = tmpy; 264 sp->len += sp->dim*CHUNCKSIZE; 265 } 266 for (j=0; j<sp->dim; j++) { 267 x = xx[j]; y = yy[j]; 268 k = sp->loc + j; 269 for (i=0; i<n; i++) { 270 if (x[i] > sp->xmax) sp->xmax = x[i]; 271 if (x[i] < sp->xmin) sp->xmin = x[i]; 272 if (y[i] > sp->ymax) sp->ymax = y[i]; 273 if (y[i] < sp->ymin) sp->ymin = y[i]; 274 275 sp->x[k] = x[i]; 276 sp->y[k] = y[i]; 277 k += sp->dim; 278 } 279 } 280 sp->loc += n*sp->dim; 281 sp->nopts += n; 282 PetscFunctionReturn(0); 283 } 284 285 /*@ 286 PetscDrawSPDraw - Redraws a scatter plot. 287 288 Collective on PetscDrawSP 289 290 Input Parameter: 291 + sp - the line graph context 292 - clear - clear the window before drawing the new plot 293 294 Level: intermediate 295 296 .seealso: PetscDrawLGDraw(), PetscDrawLGSPDraw(), PetscDrawSP, PetscDrawSPCreate(), PetscDrawSPReset(), PetscDrawSPAddPoint(), PetscDrawSPAddPoints() 297 298 @*/ 299 PetscErrorCode PetscDrawSPDraw(PetscDrawSP sp, PetscBool clear) 300 { 301 PetscReal xmin,xmax,ymin,ymax; 302 PetscErrorCode ierr; 303 PetscMPIInt rank; 304 PetscBool isnull; 305 PetscDraw draw; 306 307 PetscFunctionBegin; 308 PetscValidHeaderSpecific(sp,PETSC_DRAWSP_CLASSID,1); 309 ierr = PetscDrawIsNull(sp->win,&isnull);CHKERRQ(ierr); 310 if (isnull) PetscFunctionReturn(0); 311 ierr = MPI_Comm_rank(PetscObjectComm((PetscObject)sp),&rank);CHKERRMPI(ierr); 312 313 if (sp->xmin > sp->xmax || sp->ymin > sp->ymax) PetscFunctionReturn(0); 314 if (sp->nopts < 1) PetscFunctionReturn(0); 315 316 draw = sp->win; 317 if (clear) { 318 ierr = PetscDrawCheckResizedWindow(draw);CHKERRQ(ierr); 319 ierr = PetscDrawClear(draw);CHKERRQ(ierr); 320 } 321 322 xmin = sp->xmin; xmax = sp->xmax; ymin = sp->ymin; ymax = sp->ymax; 323 ierr = PetscDrawAxisSetLimits(sp->axis,xmin,xmax,ymin,ymax);CHKERRQ(ierr); 324 ierr = PetscDrawAxisDraw(sp->axis);CHKERRQ(ierr); 325 326 ierr = PetscDrawCollectiveBegin(draw);CHKERRQ(ierr); 327 if (!rank) { 328 int i,j,dim=sp->dim,nopts=sp->nopts; 329 for (i=0; i<dim; i++) { 330 for (j=0; j<nopts; j++) { 331 ierr = PetscDrawPoint(draw,sp->x[j*dim+i],sp->y[j*dim+i],PETSC_DRAW_RED);CHKERRQ(ierr); 332 } 333 } 334 } 335 ierr = PetscDrawCollectiveEnd(draw);CHKERRQ(ierr); 336 337 ierr = PetscDrawFlush(draw);CHKERRQ(ierr); 338 ierr = PetscDrawPause(draw);CHKERRQ(ierr); 339 PetscFunctionReturn(0); 340 } 341 342 /*@ 343 PetscDrawSPSave - Saves a drawn image 344 345 Collective on PetscDrawSP 346 347 Input Parameter: 348 . sp - the scatter plot context 349 350 Level: intermediate 351 352 .seealso: PetscDrawSPCreate(), PetscDrawSPGetDraw(), PetscDrawSetSave(), PetscDrawSave() 353 @*/ 354 PetscErrorCode PetscDrawSPSave(PetscDrawSP sp) 355 { 356 PetscErrorCode ierr; 357 358 PetscFunctionBegin; 359 PetscValidHeaderSpecific(sp,PETSC_DRAWSP_CLASSID,1); 360 ierr = PetscDrawSave(sp->win);CHKERRQ(ierr); 361 PetscFunctionReturn(0); 362 } 363 364 /*@ 365 PetscDrawSPSetLimits - Sets the axis limits for a scatter plot If more 366 points are added after this call, the limits will be adjusted to 367 include those additional points. 368 369 Logically Collective on PetscDrawSP 370 371 Input Parameters: 372 + xsp - the line graph context 373 - x_min,x_max,y_min,y_max - the limits 374 375 Level: intermediate 376 377 .seealso: PetscDrawSP, PetscDrawSPCreate(), PetscDrawSPDraw(), PetscDrawSPAddPoint(), PetscDrawSPAddPoints(), PetscDrawSPGetAxis() 378 @*/ 379 PetscErrorCode PetscDrawSPSetLimits(PetscDrawSP sp,PetscReal x_min,PetscReal x_max,PetscReal y_min,PetscReal y_max) 380 { 381 PetscFunctionBegin; 382 PetscValidHeaderSpecific(sp,PETSC_DRAWSP_CLASSID,1); 383 sp->xmin = x_min; 384 sp->xmax = x_max; 385 sp->ymin = y_min; 386 sp->ymax = y_max; 387 PetscFunctionReturn(0); 388 } 389 390 /*@C 391 PetscDrawSPGetAxis - Gets the axis context associated with a line graph. 392 This is useful if one wants to change some axis property, such as 393 labels, color, etc. The axis context should not be destroyed by the 394 application code. 395 396 Not Collective, if PetscDrawSP is parallel then PetscDrawAxis is parallel 397 398 Input Parameter: 399 . sp - the line graph context 400 401 Output Parameter: 402 . axis - the axis context 403 404 Level: intermediate 405 406 .seealso: PetscDrawSP, PetscDrawSPCreate(), PetscDrawSPDraw(), PetscDrawSPAddPoint(), PetscDrawSPAddPoints(), PetscDrawAxis, PetscDrawAxisCreate() 407 408 @*/ 409 PetscErrorCode PetscDrawSPGetAxis(PetscDrawSP sp,PetscDrawAxis *axis) 410 { 411 PetscFunctionBegin; 412 PetscValidHeaderSpecific(sp,PETSC_DRAWSP_CLASSID,1); 413 PetscValidPointer(axis,2); 414 *axis = sp->axis; 415 PetscFunctionReturn(0); 416 } 417 418 /*@C 419 PetscDrawSPGetDraw - Gets the draw context associated with a line graph. 420 421 Not Collective, PetscDraw is parallel if PetscDrawSP is parallel 422 423 Input Parameter: 424 . sp - the line graph context 425 426 Output Parameter: 427 . draw - the draw context 428 429 Level: intermediate 430 431 .seealso: PetscDrawSP, PetscDrawSPCreate(), PetscDrawSPDraw(), PetscDraw 432 @*/ 433 PetscErrorCode PetscDrawSPGetDraw(PetscDrawSP sp,PetscDraw *draw) 434 { 435 PetscFunctionBegin; 436 PetscValidHeaderSpecific(sp,PETSC_DRAWSP_CLASSID,1); 437 PetscValidPointer(draw,2); 438 *draw = sp->win; 439 PetscFunctionReturn(0); 440 } 441