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