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