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