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