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