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 PetscErrorCode ierr; 49 PetscBool isnull; 50 PetscObject obj = (PetscObject)draw; 51 PetscDrawSP sp; 52 53 PetscFunctionBegin; 54 PetscValidHeaderSpecific(draw,PETSC_DRAW_CLASSID,1); 55 PetscValidPointer(drawsp,3); 56 ierr = PetscObjectTypeCompare(obj,PETSC_DRAW_NULL,&isnull);CHKERRQ(ierr); 57 if (isnull) { 58 ierr = PetscDrawOpenNull(PetscObjectComm((PetscObject)obj),(PetscDraw*)drawsp);CHKERRQ(ierr); 59 PetscFunctionReturn(0); 60 } 61 ierr = PetscHeaderCreate(sp,_p_PetscDrawSP,int,PETSC_DRAWSP_CLASSID,"PetscDrawSP","Scatter plot","Draw",PetscObjectComm((PetscObject)obj),PetscDrawSPDestroy,0);CHKERRQ(ierr); 62 63 sp->view = 0; 64 sp->destroy = 0; 65 sp->nopts = 0; 66 sp->win = draw; 67 sp->dim = dim; 68 sp->xmin = 1.e20; 69 sp->ymin = 1.e20; 70 sp->xmax = -1.e20; 71 sp->ymax = -1.e20; 72 73 ierr = PetscMalloc2(dim*CHUNCKSIZE,&sp->x,dim*CHUNCKSIZE,&sp->y);CHKERRQ(ierr); 74 ierr = PetscLogObjectMemory((PetscObject)sp,2*dim*CHUNCKSIZE*sizeof(PetscReal));CHKERRQ(ierr); 75 76 sp->len = dim*CHUNCKSIZE; 77 sp->loc = 0; 78 79 ierr = PetscDrawAxisCreate(draw,&sp->axis);CHKERRQ(ierr); 80 ierr = PetscLogObjectParent((PetscObject)sp,(PetscObject)sp->axis);CHKERRQ(ierr); 81 82 *drawsp = sp; 83 PetscFunctionReturn(0); 84 } 85 86 #undef __FUNCT__ 87 #define __FUNCT__ "PetscDrawSPSetDimension" 88 /*@ 89 PetscDrawSPSetDimension - Change the number of sets of points that are to be drawn. 90 91 Not Collective (ignored on all processors except processor 0 of PetscDrawSP) 92 93 Input Parameter: 94 + sp - the line graph context. 95 - dim - the number of curves. 96 97 Level: intermediate 98 99 Concepts: scatter plot^setting number of data types 100 101 @*/ 102 PetscErrorCode PetscDrawSPSetDimension(PetscDrawSP sp,int dim) 103 { 104 PetscErrorCode ierr; 105 106 PetscFunctionBegin; 107 if (sp && ((PetscObject)sp)->classid == PETSC_DRAW_CLASSID) PetscFunctionReturn(0); 108 PetscValidHeaderSpecific(sp,PETSC_DRAWSP_CLASSID,1); 109 if (sp->dim == dim) PetscFunctionReturn(0); 110 111 ierr = PetscFree2(sp->x,sp->y);CHKERRQ(ierr); 112 sp->dim = dim; 113 ierr = PetscMalloc2(dim*CHUNCKSIZE,&sp->x,dim*CHUNCKSIZE,&sp->y);CHKERRQ(ierr); 114 ierr = PetscLogObjectMemory((PetscObject)sp,2*dim*CHUNCKSIZE*sizeof(PetscReal));CHKERRQ(ierr); 115 sp->len = dim*CHUNCKSIZE; 116 PetscFunctionReturn(0); 117 } 118 119 #undef __FUNCT__ 120 #define __FUNCT__ "PetscDrawSPReset" 121 /*@ 122 PetscDrawSPReset - Clears line graph to allow for reuse with new data. 123 124 Not Collective (ignored on all processors except processor 0 of PetscDrawSP) 125 126 Input Parameter: 127 . sp - the line graph context. 128 129 Level: intermediate 130 131 Concepts: scatter plot^resetting 132 133 @*/ 134 PetscErrorCode PetscDrawSPReset(PetscDrawSP sp) 135 { 136 PetscFunctionBegin; 137 if (sp && ((PetscObject)sp)->classid == PETSC_DRAW_CLASSID) PetscFunctionReturn(0); 138 PetscValidHeaderSpecific(sp,PETSC_DRAWSP_CLASSID,1); 139 sp->xmin = 1.e20; 140 sp->ymin = 1.e20; 141 sp->xmax = -1.e20; 142 sp->ymax = -1.e20; 143 sp->loc = 0; 144 sp->nopts = 0; 145 PetscFunctionReturn(0); 146 } 147 148 #undef __FUNCT__ 149 #define __FUNCT__ "PetscDrawSPDestroy" 150 /*@C 151 PetscDrawSPDestroy - Frees all space taken up by scatter plot data structure. 152 153 Collective over PetscDrawSP 154 155 Input Parameter: 156 . sp - the line graph context 157 158 Level: intermediate 159 160 .seealso: PetscDrawSPCreate() 161 @*/ 162 PetscErrorCode PetscDrawSPDestroy(PetscDrawSP *sp) 163 { 164 PetscErrorCode ierr; 165 166 PetscFunctionBegin; 167 if (!*sp) PetscFunctionReturn(0); 168 PetscValidHeader(*sp,1); 169 170 if (--((PetscObject)(*sp))->refct > 0) PetscFunctionReturn(0); 171 if (((PetscObject)(*sp))->classid == PETSC_DRAW_CLASSID) { 172 ierr = PetscDrawDestroy((PetscDraw*) sp);CHKERRQ(ierr); 173 PetscFunctionReturn(0); 174 } 175 ierr = PetscDrawAxisDestroy(&(*sp)->axis);CHKERRQ(ierr); 176 ierr = PetscFree2((*sp)->x,(*sp)->y);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 Not Collective (ignored on all processors except processor 0 of 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 && ((PetscObject)sp)->classid == PETSC_DRAW_CLASSID) PetscFunctionReturn(0); 206 207 PetscValidHeaderSpecific(sp,PETSC_DRAWSP_CLASSID,1); 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 Not Collective (ignored on all processors except processor 0 of 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 && ((PetscObject)sp)->classid == PETSC_DRAW_CLASSID) 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 Not Collective (ignored on all processors except processor 0 of 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=sp->xmin,xmax=sp->xmax,ymin=sp->ymin,ymax=sp->ymax; 314 PetscErrorCode ierr; 315 PetscInt i,j,dim = sp->dim,nopts = sp->nopts; 316 PetscMPIInt rank; 317 PetscDraw draw = sp->win; 318 319 PetscFunctionBegin; 320 if (sp && ((PetscObject)sp)->classid == PETSC_DRAW_CLASSID) PetscFunctionReturn(0); 321 PetscValidHeaderSpecific(sp,PETSC_DRAWSP_CLASSID,1); 322 323 if (nopts < 1) PetscFunctionReturn(0); 324 if (xmin > xmax || ymin > ymax) PetscFunctionReturn(0); 325 if (clear) { 326 ierr = PetscDrawCheckResizedWindow(draw);CHKERRQ(ierr); 327 ierr = PetscDrawClear(draw);CHKERRQ(ierr); 328 } 329 ierr = PetscDrawAxisSetLimits(sp->axis,xmin,xmax,ymin,ymax);CHKERRQ(ierr); 330 ierr = PetscDrawAxisDraw(sp->axis);CHKERRQ(ierr); 331 332 ierr = MPI_Comm_rank(PetscObjectComm((PetscObject)sp),&rank);CHKERRQ(ierr); 333 if (!rank) { 334 for (i=0; i<dim; i++) { 335 for (j=0; j<nopts; j++) { 336 ierr = PetscDrawPoint(draw,sp->x[j*dim+i],sp->y[j*dim+i],PETSC_DRAW_RED);CHKERRQ(ierr); 337 } 338 } 339 } 340 ierr = PetscDrawFlush(sp->win);CHKERRQ(ierr); 341 ierr = PetscDrawPause(sp->win);CHKERRQ(ierr); 342 PetscFunctionReturn(0); 343 } 344 345 #undef __FUNCT__ 346 #define __FUNCT__ "PetscDrawSPSetLimits" 347 /*@ 348 PetscDrawSPSetLimits - Sets the axis limits for a scatter plot If more 349 points are added after this call, the limits will be adjusted to 350 include those additional points. 351 352 Not Collective (ignored on all processors except processor 0 of PetscDrawSP) 353 354 Input Parameters: 355 + xsp - the line graph context 356 - x_min,x_max,y_min,y_max - the limits 357 358 Level: intermediate 359 360 Concepts: scatter plot^setting axis 361 362 @*/ 363 PetscErrorCode PetscDrawSPSetLimits(PetscDrawSP sp,PetscReal x_min,PetscReal x_max,PetscReal y_min,PetscReal y_max) 364 { 365 PetscFunctionBegin; 366 if (sp && ((PetscObject)sp)->classid == PETSC_DRAW_CLASSID) PetscFunctionReturn(0); 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 #undef __FUNCT__ 376 #define __FUNCT__ "PetscDrawSPGetAxis" 377 /*@C 378 PetscDrawSPGetAxis - Gets the axis context associated with a line graph. 379 This is useful if one wants to change some axis property, such as 380 labels, color, etc. The axis context should not be destroyed by the 381 application code. 382 383 Not Collective (except PetscDrawAxis can only be used on processor 0 of PetscDrawSP) 384 385 Input Parameter: 386 . sp - the line graph context 387 388 Output Parameter: 389 . axis - the axis context 390 391 Level: intermediate 392 393 @*/ 394 PetscErrorCode PetscDrawSPGetAxis(PetscDrawSP sp,PetscDrawAxis *axis) 395 { 396 PetscFunctionBegin; 397 if (sp && ((PetscObject)sp)->classid == PETSC_DRAW_CLASSID) { 398 *axis = 0; 399 PetscFunctionReturn(0); 400 } 401 PetscValidHeaderSpecific(sp,PETSC_DRAWSP_CLASSID,1); 402 *axis = sp->axis; 403 PetscFunctionReturn(0); 404 } 405 406 #undef __FUNCT__ 407 #define __FUNCT__ "PetscDrawSPGetDraw" 408 /*@C 409 PetscDrawSPGetDraw - Gets the draw context associated with a line graph. 410 411 Not Collective, PetscDraw is parallel if PetscDrawSP is parallel 412 413 Input Parameter: 414 . sp - the line graph context 415 416 Output Parameter: 417 . draw - the draw context 418 419 Level: intermediate 420 421 @*/ 422 PetscErrorCode PetscDrawSPGetDraw(PetscDrawSP sp,PetscDraw *draw) 423 { 424 PetscFunctionBegin; 425 PetscValidHeader(sp,1); 426 PetscValidPointer(draw,2); 427 if (sp && ((PetscObject)sp)->classid == PETSC_DRAW_CLASSID) *draw = (PetscDraw)sp; 428 else *draw = sp->win; 429 PetscFunctionReturn(0); 430 } 431