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