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 /*@C 225 PetscDrawSPAddPoints - Adds several points to each of the scatter plots. 226 227 Logically Collective on PetscDrawSP 228 229 Input Parameters: 230 + sp - the LineGraph data structure 231 . xx,yy - points to two arrays of pointers that point to arrays 232 containing the new x and y points for each curve. 233 - n - number of points being added 234 235 Level: intermediate 236 237 Notes: 238 the new points will not be displayed until a call to PetscDrawSPDraw() is made 239 240 .seealso: PetscDrawSPAddPoint(), PetscDrawSP, PetscDrawSPCreate(), PetscDrawSPReset(), PetscDrawSPDraw() 241 @*/ 242 PetscErrorCode PetscDrawSPAddPoints(PetscDrawSP sp,int n,PetscReal **xx,PetscReal **yy) 243 { 244 PetscErrorCode ierr; 245 PetscInt i,j,k; 246 PetscReal *x,*y; 247 248 PetscFunctionBegin; 249 PetscValidHeaderSpecific(sp,PETSC_DRAWSP_CLASSID,1); 250 251 if (sp->loc+n*sp->dim >= sp->len) { /* allocate more space */ 252 PetscReal *tmpx,*tmpy; 253 PetscInt chunk = CHUNCKSIZE; 254 if (n > chunk) chunk = n; 255 ierr = PetscMalloc2(sp->len+sp->dim*chunk,&tmpx,sp->len+sp->dim*chunk,&tmpy);CHKERRQ(ierr); 256 ierr = PetscLogObjectMemory((PetscObject)sp,2*sp->dim*CHUNCKSIZE*sizeof(PetscReal));CHKERRQ(ierr); 257 ierr = PetscArraycpy(tmpx,sp->x,sp->len);CHKERRQ(ierr); 258 ierr = PetscArraycpy(tmpy,sp->y,sp->len);CHKERRQ(ierr); 259 ierr = PetscFree2(sp->x,sp->y);CHKERRQ(ierr); 260 261 sp->x = tmpx; 262 sp->y = tmpy; 263 sp->len += sp->dim*CHUNCKSIZE; 264 } 265 for (j=0; j<sp->dim; j++) { 266 x = xx[j]; y = yy[j]; 267 k = sp->loc + j; 268 for (i=0; i<n; i++) { 269 if (x[i] > sp->xmax) sp->xmax = x[i]; 270 if (x[i] < sp->xmin) sp->xmin = x[i]; 271 if (y[i] > sp->ymax) sp->ymax = y[i]; 272 if (y[i] < sp->ymin) sp->ymin = y[i]; 273 274 sp->x[k] = x[i]; 275 sp->y[k] = y[i]; 276 k += sp->dim; 277 } 278 } 279 sp->loc += n*sp->dim; 280 sp->nopts += n; 281 PetscFunctionReturn(0); 282 } 283 284 /*@ 285 PetscDrawSPDraw - Redraws a scatter plot. 286 287 Collective on PetscDrawSP 288 289 Input Parameter: 290 + sp - the line graph context 291 - clear - clear the window before drawing the new plot 292 293 Level: intermediate 294 295 .seealso: PetscDrawLGDraw(), PetscDrawLGSPDraw(), PetscDrawSP, PetscDrawSPCreate(), PetscDrawSPReset(), PetscDrawSPAddPoint(), PetscDrawSPAddPoints() 296 297 @*/ 298 PetscErrorCode PetscDrawSPDraw(PetscDrawSP sp, PetscBool clear) 299 { 300 PetscReal xmin,xmax,ymin,ymax; 301 PetscErrorCode ierr; 302 PetscMPIInt rank; 303 PetscBool isnull; 304 PetscDraw draw; 305 306 PetscFunctionBegin; 307 PetscValidHeaderSpecific(sp,PETSC_DRAWSP_CLASSID,1); 308 ierr = PetscDrawIsNull(sp->win,&isnull);CHKERRQ(ierr); 309 if (isnull) PetscFunctionReturn(0); 310 ierr = MPI_Comm_rank(PetscObjectComm((PetscObject)sp),&rank);CHKERRMPI(ierr); 311 312 if (sp->xmin > sp->xmax || sp->ymin > sp->ymax) PetscFunctionReturn(0); 313 if (sp->nopts < 1) PetscFunctionReturn(0); 314 315 draw = sp->win; 316 if (clear) { 317 ierr = PetscDrawCheckResizedWindow(draw);CHKERRQ(ierr); 318 ierr = PetscDrawClear(draw);CHKERRQ(ierr); 319 } 320 321 xmin = sp->xmin; xmax = sp->xmax; ymin = sp->ymin; ymax = sp->ymax; 322 ierr = PetscDrawAxisSetLimits(sp->axis,xmin,xmax,ymin,ymax);CHKERRQ(ierr); 323 ierr = PetscDrawAxisDraw(sp->axis);CHKERRQ(ierr); 324 325 ierr = PetscDrawCollectiveBegin(draw);CHKERRQ(ierr); 326 if (!rank) { 327 int i,j,dim=sp->dim,nopts=sp->nopts; 328 for (i=0; i<dim; i++) { 329 for (j=0; j<nopts; j++) { 330 ierr = PetscDrawPoint(draw,sp->x[j*dim+i],sp->y[j*dim+i],PETSC_DRAW_RED);CHKERRQ(ierr); 331 } 332 } 333 } 334 ierr = PetscDrawCollectiveEnd(draw);CHKERRQ(ierr); 335 336 ierr = PetscDrawFlush(draw);CHKERRQ(ierr); 337 ierr = PetscDrawPause(draw);CHKERRQ(ierr); 338 PetscFunctionReturn(0); 339 } 340 341 /*@ 342 PetscDrawSPSave - Saves a drawn image 343 344 Collective on PetscDrawSP 345 346 Input Parameter: 347 . sp - the scatter plot context 348 349 Level: intermediate 350 351 .seealso: PetscDrawSPCreate(), PetscDrawSPGetDraw(), PetscDrawSetSave(), PetscDrawSave() 352 @*/ 353 PetscErrorCode PetscDrawSPSave(PetscDrawSP sp) 354 { 355 PetscErrorCode ierr; 356 357 PetscFunctionBegin; 358 PetscValidHeaderSpecific(sp,PETSC_DRAWSP_CLASSID,1); 359 ierr = PetscDrawSave(sp->win);CHKERRQ(ierr); 360 PetscFunctionReturn(0); 361 } 362 363 /*@ 364 PetscDrawSPSetLimits - Sets the axis limits for a scatter plot If more 365 points are added after this call, the limits will be adjusted to 366 include those additional points. 367 368 Logically Collective on PetscDrawSP 369 370 Input Parameters: 371 + xsp - the line graph context 372 - x_min,x_max,y_min,y_max - the limits 373 374 Level: intermediate 375 376 .seealso: PetscDrawSP, PetscDrawSPCreate(), PetscDrawSPDraw(), PetscDrawSPAddPoint(), PetscDrawSPAddPoints(), PetscDrawSPGetAxis() 377 @*/ 378 PetscErrorCode PetscDrawSPSetLimits(PetscDrawSP sp,PetscReal x_min,PetscReal x_max,PetscReal y_min,PetscReal y_max) 379 { 380 PetscFunctionBegin; 381 PetscValidHeaderSpecific(sp,PETSC_DRAWSP_CLASSID,1); 382 sp->xmin = x_min; 383 sp->xmax = x_max; 384 sp->ymin = y_min; 385 sp->ymax = y_max; 386 PetscFunctionReturn(0); 387 } 388 389 /*@C 390 PetscDrawSPGetAxis - Gets the axis context associated with a line graph. 391 This is useful if one wants to change some axis property, such as 392 labels, color, etc. The axis context should not be destroyed by the 393 application code. 394 395 Not Collective, if PetscDrawSP is parallel then PetscDrawAxis is parallel 396 397 Input Parameter: 398 . sp - the line graph context 399 400 Output Parameter: 401 . axis - the axis context 402 403 Level: intermediate 404 405 .seealso: PetscDrawSP, PetscDrawSPCreate(), PetscDrawSPDraw(), PetscDrawSPAddPoint(), PetscDrawSPAddPoints(), PetscDrawAxis, PetscDrawAxisCreate() 406 407 @*/ 408 PetscErrorCode PetscDrawSPGetAxis(PetscDrawSP sp,PetscDrawAxis *axis) 409 { 410 PetscFunctionBegin; 411 PetscValidHeaderSpecific(sp,PETSC_DRAWSP_CLASSID,1); 412 PetscValidPointer(axis,2); 413 *axis = sp->axis; 414 PetscFunctionReturn(0); 415 } 416 417 /*@C 418 PetscDrawSPGetDraw - Gets the draw context associated with a line graph. 419 420 Not Collective, PetscDraw is parallel if PetscDrawSP is parallel 421 422 Input Parameter: 423 . sp - the line graph context 424 425 Output Parameter: 426 . draw - the draw context 427 428 Level: intermediate 429 430 .seealso: PetscDrawSP, PetscDrawSPCreate(), PetscDrawSPDraw(), PetscDraw 431 @*/ 432 PetscErrorCode PetscDrawSPGetDraw(PetscDrawSP sp,PetscDraw *draw) 433 { 434 PetscFunctionBegin; 435 PetscValidHeaderSpecific(sp,PETSC_DRAWSP_CLASSID,1); 436 PetscValidPointer(draw,2); 437 *draw = sp->win; 438 PetscFunctionReturn(0); 439 } 440