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