1 2 #include <../src/sys/classes/draw/utils/lgimpl.h> 3 PetscClassId PETSC_DRAWLG_CLASSID = 0; 4 5 #undef __FUNCT__ 6 #define __FUNCT__ "PetscDrawLGGetAxis" 7 /*@ 8 PetscDrawLGGetAxis - Gets the axis context associated with a line graph. 9 This is useful if one wants to change some axis property, such as 10 labels, color, etc. The axis context should not be destroyed by the 11 application code. 12 13 Not Collective, if PetscDrawLG is parallel then PetscDrawAxis is parallel 14 15 Input Parameter: 16 . lg - the line graph context 17 18 Output Parameter: 19 . axis - the axis context 20 21 Level: advanced 22 23 @*/ 24 PetscErrorCode PetscDrawLGGetAxis(PetscDrawLG lg,PetscDrawAxis *axis) 25 { 26 PetscFunctionBegin; 27 if (lg && ((PetscObject)lg)->classid == PETSC_DRAW_CLASSID) { 28 *axis = 0; 29 PetscFunctionReturn(0); 30 } 31 PetscValidHeaderSpecific(lg,PETSC_DRAWLG_CLASSID,1); 32 PetscValidPointer(axis,2); 33 *axis = lg->axis; 34 PetscFunctionReturn(0); 35 } 36 37 #undef __FUNCT__ 38 #define __FUNCT__ "PetscDrawLGGetDraw" 39 /*@ 40 PetscDrawLGGetDraw - Gets the draw context associated with a line graph. 41 42 Not Collective, if PetscDrawLG is parallel then PetscDraw is parallel 43 44 Input Parameter: 45 . lg - the line graph context 46 47 Output Parameter: 48 . draw - the draw context 49 50 Level: intermediate 51 52 @*/ 53 PetscErrorCode PetscDrawLGGetDraw(PetscDrawLG lg,PetscDraw *draw) 54 { 55 PetscFunctionBegin; 56 PetscValidHeader(lg,1); 57 PetscValidPointer(draw,2); 58 if (((PetscObject)lg)->classid == PETSC_DRAW_CLASSID) { 59 *draw = (PetscDraw)lg; 60 } else { 61 PetscValidHeaderSpecific(lg,PETSC_DRAWLG_CLASSID,1); 62 *draw = lg->win; 63 } 64 PetscFunctionReturn(0); 65 } 66 67 68 #undef __FUNCT__ 69 #define __FUNCT__ "PetscDrawLGSPDraw" 70 /*@ 71 PetscDrawLGSPDraw - Redraws a line graph. 72 73 Not Collective,but ignored by all processors except processor 0 in PetscDrawLG 74 75 Input Parameter: 76 . lg - the line graph context 77 78 Level: intermediate 79 80 .seealso: PetscDrawLGDraw(), PetscDrawSPDraw() 81 82 Developer Notes: This code cheats and uses the fact that the LG and SP structs are the same 83 84 @*/ 85 PetscErrorCode PetscDrawLGSPDraw(PetscDrawLG lg,PetscDrawSP spin) 86 { 87 PetscDrawLG sp = (PetscDrawLG)spin; 88 PetscReal xmin,xmax,ymin,ymax; 89 PetscErrorCode ierr; 90 int i,j,dim,nopts,rank; 91 PetscDraw draw = lg->win; 92 93 PetscFunctionBegin; 94 if (lg && ((PetscObject)lg)->classid == PETSC_DRAW_CLASSID) PetscFunctionReturn(0); 95 PetscValidHeaderSpecific(lg,PETSC_DRAWLG_CLASSID,1); 96 PetscValidHeaderSpecific(sp,PETSC_DRAWSP_CLASSID,2); 97 98 xmin = PetscMin(lg->xmin,sp->xmin); 99 ymin = PetscMin(lg->ymin,sp->ymin); 100 xmax = PetscMax(lg->xmax,sp->xmax); 101 ymax = PetscMax(lg->ymax,sp->ymax); 102 103 ierr = PetscDrawClear(draw);CHKERRQ(ierr); 104 ierr = PetscDrawAxisSetLimits(lg->axis,xmin,xmax,ymin,ymax);CHKERRQ(ierr); 105 ierr = PetscDrawAxisDraw(lg->axis);CHKERRQ(ierr); 106 107 ierr = MPI_Comm_rank(((PetscObject)lg)->comm,&rank);CHKERRQ(ierr); 108 if (!rank) { 109 110 dim = lg->dim; 111 nopts = lg->nopts; 112 for (i=0; i<dim; i++) { 113 for (j=1; j<nopts; j++) { 114 ierr = PetscDrawLine(draw,lg->x[(j-1)*dim+i],lg->y[(j-1)*dim+i],lg->x[j*dim+i],lg->y[j*dim+i],PETSC_DRAW_BLACK+i);CHKERRQ(ierr); 115 if (lg->use_dots) { 116 ierr = PetscDrawString(draw,lg->x[j*dim+i],lg->y[j*dim+i],PETSC_DRAW_RED,"x");CHKERRQ(ierr); 117 } 118 } 119 } 120 121 dim = sp->dim; 122 nopts = sp->nopts; 123 for (i=0; i<dim; i++) { 124 for (j=0; j<nopts; j++) { 125 ierr = PetscDrawString(draw,sp->x[j*dim+i],sp->y[j*dim+i],PETSC_DRAW_RED,"x");CHKERRQ(ierr); 126 } 127 } 128 } 129 ierr = PetscDrawFlush(lg->win);CHKERRQ(ierr); 130 ierr = PetscDrawPause(lg->win);CHKERRQ(ierr); 131 PetscFunctionReturn(0); 132 } 133 134 135 #undef __FUNCT__ 136 #define __FUNCT__ "PetscDrawLGCreate" 137 /*@ 138 PetscDrawLGCreate - Creates a line graph data structure. 139 140 Collective over PetscDraw 141 142 Input Parameters: 143 + draw - the window where the graph will be made. 144 - dim - the number of curves which will be drawn 145 146 Output Parameters: 147 . outctx - the line graph context 148 149 Level: intermediate 150 151 Concepts: line graph^creating 152 153 .seealso: PetscDrawLGDestroy() 154 @*/ 155 PetscErrorCode PetscDrawLGCreate(PetscDraw draw,PetscInt dim,PetscDrawLG *outctx) 156 { 157 PetscErrorCode ierr; 158 PetscBool isnull; 159 PetscObject obj = (PetscObject)draw; 160 PetscDrawLG lg; 161 162 PetscFunctionBegin; 163 PetscValidHeaderSpecific(draw,PETSC_DRAW_CLASSID,1); 164 PetscValidPointer(outctx,2); 165 ierr = PetscObjectTypeCompare(obj,PETSC_DRAW_NULL,&isnull);CHKERRQ(ierr); 166 if (isnull) { 167 ierr = PetscDrawOpenNull(((PetscObject)obj)->comm,(PetscDraw*)outctx);CHKERRQ(ierr); 168 PetscFunctionReturn(0); 169 } 170 ierr = PetscHeaderCreate(lg,_p_PetscDrawLG,int,PETSC_DRAWLG_CLASSID,0,"PetscDrawLG","Line graph","Draw",((PetscObject)obj)->comm,PetscDrawLGDestroy,0);CHKERRQ(ierr); 171 lg->view = 0; 172 lg->destroy = 0; 173 lg->nopts = 0; 174 lg->win = draw; 175 lg->dim = dim; 176 lg->xmin = 1.e20; 177 lg->ymin = 1.e20; 178 lg->xmax = -1.e20; 179 lg->ymax = -1.e20; 180 ierr = PetscMalloc2(dim*CHUNCKSIZE,PetscReal,&lg->x,dim*CHUNCKSIZE,PetscReal,&lg->y);CHKERRQ(ierr); 181 ierr = PetscLogObjectMemory(lg,2*dim*CHUNCKSIZE*sizeof(PetscReal));CHKERRQ(ierr); 182 lg->len = dim*CHUNCKSIZE; 183 lg->loc = 0; 184 lg->use_dots= PETSC_FALSE; 185 ierr = PetscDrawAxisCreate(draw,&lg->axis);CHKERRQ(ierr); 186 ierr = PetscLogObjectParent(lg,lg->axis);CHKERRQ(ierr); 187 *outctx = lg; 188 PetscFunctionReturn(0); 189 } 190 191 #undef __FUNCT__ 192 #define __FUNCT__ "PetscDrawLGSetColors" 193 /*@ 194 PetscDrawLGSetColors - Sets the color of each line graph drawn 195 196 Logically Collective over PetscDrawLG 197 198 Input Parameter: 199 + lg - the line graph context. 200 - colors - the colors 201 202 Level: intermediate 203 204 Concepts: line graph^setting number of lines 205 206 @*/ 207 PetscErrorCode PetscDrawLGSetColors(PetscDrawLG lg,const int *colors) 208 { 209 PetscErrorCode ierr; 210 211 PetscFunctionBegin; 212 if (lg && ((PetscObject)lg)->classid == PETSC_DRAW_CLASSID) PetscFunctionReturn(0); 213 PetscValidHeaderSpecific(lg,PETSC_DRAWLG_CLASSID,1); 214 ierr = PetscFree(lg->colors);CHKERRQ(ierr); 215 ierr = PetscMalloc(lg->dim*sizeof(int),&lg->colors);CHKERRQ(ierr); 216 ierr = PetscMemcpy(lg->colors,colors,lg->dim*sizeof(int));CHKERRQ(ierr); 217 PetscFunctionReturn(0); 218 } 219 220 #undef __FUNCT__ 221 #undef __FUNCT__ 222 #define __FUNCT__ "PetscDrawLGSetLegend" 223 /*@C 224 PetscDrawLGSetLegend - sets the names of each curve plotted 225 226 Logically Collective over PetscDrawLG 227 228 Input Parameter: 229 + lg - the line graph context. 230 - names - the names for each curve 231 232 Level: intermediate 233 234 Concepts: line graph^setting number of lines 235 236 @*/ 237 PetscErrorCode PetscDrawLGSetLegend(PetscDrawLG lg,const char *const *names) 238 { 239 PetscErrorCode ierr; 240 PetscInt i; 241 242 PetscFunctionBegin; 243 if (lg && ((PetscObject)lg)->classid == PETSC_DRAW_CLASSID) PetscFunctionReturn(0); 244 PetscValidHeaderSpecific(lg,PETSC_DRAWLG_CLASSID,1); 245 246 if (lg->legend) { 247 for (i=0; i<lg->dim; i++) { 248 ierr = PetscFree(lg->legend[i]);CHKERRQ(ierr); 249 } 250 ierr = PetscFree(lg->legend);CHKERRQ(ierr); 251 } 252 if (names) { 253 ierr = PetscMalloc(lg->dim*sizeof(char**),&lg->legend);CHKERRQ(ierr); 254 for (i=0; i<lg->dim; i++) { 255 ierr = PetscStrallocpy(names[i],&lg->legend[i]);CHKERRQ(ierr); 256 } 257 } 258 PetscFunctionReturn(0); 259 } 260 261 #undef __FUNCT__ 262 #define __FUNCT__ "PetscDrawLGGetDimension" 263 /*@ 264 PetscDrawLGGetDimension - Change the number of lines that are to be drawn. 265 266 Logically Collective over PetscDrawLG 267 268 Input Parameter: 269 . lg - the line graph context. 270 271 Output Parameter: 272 . dim - the number of curves. 273 274 Level: intermediate 275 276 Concepts: line graph^setting number of lines 277 278 @*/ 279 PetscErrorCode PetscDrawLGGetDimension(PetscDrawLG lg,PetscInt *dim) 280 { 281 PetscFunctionBegin; 282 if (lg && ((PetscObject)lg)->classid == PETSC_DRAW_CLASSID) PetscFunctionReturn(0); 283 PetscValidHeaderSpecific(lg,PETSC_DRAWLG_CLASSID,1); 284 *dim = lg->dim; 285 PetscFunctionReturn(0); 286 } 287 288 #undef __FUNCT__ 289 #define __FUNCT__ "PetscDrawLGSetDimension" 290 /*@ 291 PetscDrawLGSetDimension - Change the number of lines that are to be drawn. 292 293 Logically Collective over PetscDrawLG 294 295 Input Parameter: 296 + lg - the line graph context. 297 - dim - the number of curves. 298 299 Level: intermediate 300 301 Concepts: line graph^setting number of lines 302 303 @*/ 304 PetscErrorCode PetscDrawLGSetDimension(PetscDrawLG lg,PetscInt dim) 305 { 306 PetscErrorCode ierr; 307 PetscInt i; 308 309 PetscFunctionBegin; 310 if (lg && ((PetscObject)lg)->classid == PETSC_DRAW_CLASSID) PetscFunctionReturn(0); 311 PetscValidHeaderSpecific(lg,PETSC_DRAWLG_CLASSID,1); 312 PetscValidLogicalCollectiveInt(lg,dim,2); 313 if (lg->dim == dim) PetscFunctionReturn(0); 314 315 ierr = PetscFree2(lg->x,lg->y);CHKERRQ(ierr); 316 if (lg->legend) { 317 for (i=0; i<lg->dim; i++) { 318 ierr = PetscFree(lg->legend[i]);CHKERRQ(ierr); 319 } 320 ierr = PetscFree(lg->legend);CHKERRQ(ierr); 321 } 322 ierr = PetscFree(lg->colors);CHKERRQ(ierr); 323 lg->dim = dim; 324 ierr = PetscMalloc2(dim*CHUNCKSIZE,PetscReal,&lg->x,dim*CHUNCKSIZE,PetscReal,&lg->y);CHKERRQ(ierr); 325 ierr = PetscLogObjectMemory(lg,2*dim*CHUNCKSIZE*sizeof(PetscReal));CHKERRQ(ierr); 326 lg->len = dim*CHUNCKSIZE; 327 PetscFunctionReturn(0); 328 } 329 330 #undef __FUNCT__ 331 #define __FUNCT__ "PetscDrawLGReset" 332 /*@ 333 PetscDrawLGReset - Clears line graph to allow for reuse with new data. 334 335 Logically Collective over PetscDrawLG 336 337 Input Parameter: 338 . lg - the line graph context. 339 340 Level: intermediate 341 342 Concepts: line graph^restarting 343 344 @*/ 345 PetscErrorCode PetscDrawLGReset(PetscDrawLG lg) 346 { 347 PetscFunctionBegin; 348 if (lg && ((PetscObject)lg)->classid == PETSC_DRAW_CLASSID) PetscFunctionReturn(0); 349 PetscValidHeaderSpecific(lg,PETSC_DRAWLG_CLASSID,1); 350 lg->xmin = 1.e20; 351 lg->ymin = 1.e20; 352 lg->xmax = -1.e20; 353 lg->ymax = -1.e20; 354 lg->loc = 0; 355 lg->nopts = 0; 356 PetscFunctionReturn(0); 357 } 358 359 #undef __FUNCT__ 360 #define __FUNCT__ "PetscDrawLGDestroy" 361 /*@ 362 PetscDrawLGDestroy - Frees all space taken up by line graph data structure. 363 364 Collective over PetscDrawLG 365 366 Input Parameter: 367 . lg - the line graph context 368 369 Level: intermediate 370 371 .seealso: PetscDrawLGCreate() 372 @*/ 373 PetscErrorCode PetscDrawLGDestroy(PetscDrawLG *lg) 374 { 375 PetscErrorCode ierr; 376 PetscInt i; 377 378 PetscFunctionBegin; 379 if (!*lg) PetscFunctionReturn(0); 380 if (((PetscObject)(*lg))->classid != PETSC_DRAW_CLASSID) { 381 PetscValidHeaderSpecific(*lg,PETSC_DRAWLG_CLASSID,1); 382 } 383 384 if (--((PetscObject)(*lg))->refct > 0) {*lg = 0; PetscFunctionReturn(0);} 385 if (((PetscObject)(*lg))->classid == PETSC_DRAW_CLASSID) { 386 ierr = PetscObjectDestroy((PetscObject*)lg);CHKERRQ(ierr); 387 PetscFunctionReturn(0); 388 } 389 if ((*lg)->legend) { 390 for (i=0; i<(*lg)->dim; i++) { 391 ierr = PetscFree((*lg)->legend[i]);CHKERRQ(ierr); 392 } 393 ierr = PetscFree((*lg)->legend);CHKERRQ(ierr); 394 } 395 ierr = PetscFree((*lg)->colors);CHKERRQ(ierr); 396 ierr = PetscDrawAxisDestroy(&(*lg)->axis);CHKERRQ(ierr); 397 ierr = PetscFree2((*lg)->x,(*lg)->y);CHKERRQ(ierr); 398 ierr = PetscHeaderDestroy(lg);CHKERRQ(ierr); 399 PetscFunctionReturn(0); 400 } 401 #undef __FUNCT__ 402 #define __FUNCT__ "PetscDrawLGIndicateDataPoints" 403 /*@ 404 PetscDrawLGIndicateDataPoints - Causes LG to draw a big dot for each data-point. 405 406 Not Collective, but ignored by all processors except processor 0 in PetscDrawLG 407 408 Input Parameters: 409 . lg - the linegraph context 410 411 Level: intermediate 412 413 Concepts: line graph^showing points 414 415 @*/ 416 PetscErrorCode PetscDrawLGIndicateDataPoints(PetscDrawLG lg) 417 { 418 PetscFunctionBegin; 419 if (lg && ((PetscObject)lg)->classid == PETSC_DRAW_CLASSID) PetscFunctionReturn(0); 420 421 lg->use_dots = PETSC_TRUE; 422 PetscFunctionReturn(0); 423 } 424 425 #if defined(PETSC_HAVE_SETJMP_H) && defined(PETSC_HAVE_X) 426 #include <sys/types.h> 427 #include <X11/Xlib.h> 428 #include <X11/Xutil.h> 429 #include <setjmp.h> 430 static jmp_buf PetscXIOErrorJumpBuf; 431 static void PetscXIOHandler(Display *dpy) 432 { 433 longjmp(PetscXIOErrorJumpBuf, 1); 434 } 435 #endif 436 437 #undef __FUNCT__ 438 #define __FUNCT__ "PetscDrawLGDraw" 439 /*@ 440 PetscDrawLGDraw - Redraws a line graph. 441 442 Not Collective,but ignored by all processors except processor 0 in PetscDrawLG 443 444 Input Parameter: 445 . lg - the line graph context 446 447 Level: intermediate 448 449 .seealso: PetscDrawSPDraw(), PetscDrawLGSPDraw() 450 451 @*/ 452 PetscErrorCode PetscDrawLGDraw(PetscDrawLG lg) 453 { 454 PetscReal xmin=lg->xmin,xmax=lg->xmax,ymin=lg->ymin,ymax=lg->ymax; 455 PetscErrorCode ierr; 456 int i,j,dim = lg->dim,nopts = lg->nopts,rank,cl; 457 PetscDraw draw = lg->win; 458 PetscBool isnull; 459 460 PetscFunctionBegin; 461 if (lg && ((PetscObject)lg)->classid == PETSC_DRAW_CLASSID) PetscFunctionReturn(0); 462 PetscValidHeaderSpecific(lg,PETSC_DRAWLG_CLASSID,1); 463 ierr = PetscDrawIsNull(lg->win,&isnull);CHKERRQ(ierr); 464 if (isnull) PetscFunctionReturn(0); 465 466 #if defined(PETSC_HAVE_SETJMP_H) && defined(PETSC_HAVE_X) 467 if (!setjmp(PetscXIOErrorJumpBuf)) XSetIOErrorHandler((XIOErrorHandler)PetscXIOHandler); 468 else { 469 XSetIOErrorHandler(PETSC_NULL); 470 ierr = PetscDrawSetType(draw,PETSC_DRAW_NULL);CHKERRQ(ierr); 471 PetscFunctionReturn(0); 472 } 473 #endif 474 475 ierr = PetscDrawCheckResizedWindow(draw);CHKERRQ(ierr); 476 ierr = PetscDrawClear(draw);CHKERRQ(ierr); 477 ierr = PetscDrawAxisSetLimits(lg->axis,xmin,xmax,ymin,ymax);CHKERRQ(ierr); 478 ierr = PetscDrawAxisDraw(lg->axis);CHKERRQ(ierr); 479 480 ierr = MPI_Comm_rank(((PetscObject)lg)->comm,&rank);CHKERRQ(ierr); 481 if (!rank) { 482 483 for (i=0; i<dim; i++) { 484 for (j=1; j<nopts; j++) { 485 if (lg->colors) cl = lg->colors[i]; 486 else cl = PETSC_DRAW_BLACK+i; 487 ierr = PetscDrawLine(draw,lg->x[(j-1)*dim+i],lg->y[(j-1)*dim+i],lg->x[j*dim+i],lg->y[j*dim+i],cl);CHKERRQ(ierr); 488 if (lg->use_dots) { 489 ierr = PetscDrawString(draw,lg->x[j*dim+i],lg->y[j*dim+i],cl,"x");CHKERRQ(ierr); 490 } 491 } 492 } 493 } 494 if (lg->legend) { 495 PetscReal xl,yl,xr,yr,tw,th; 496 size_t len,mlen = 0; 497 int cl; 498 ierr = PetscDrawGetCoordinates(draw,&xl,&yl,&xr,&yr);CHKERRQ(ierr); 499 ierr = PetscDrawStringGetSize(draw,&tw,&th);CHKERRQ(ierr); 500 for (i=0; i<dim; i++) { 501 ierr = PetscStrlen(lg->legend[i],&len);CHKERRQ(ierr); 502 mlen = PetscMax(mlen,len); 503 } 504 ierr = PetscDrawLine(draw,xr - (mlen + 8)*tw,yr - 3*th,xr - 2*tw,yr - 3*th,PETSC_DRAW_BLACK);CHKERRQ(ierr); 505 ierr = PetscDrawLine(draw,xr - (mlen + 8)*tw,yr - 3*th,xr - (mlen + 8)*tw,yr - (4+lg->dim)*th,PETSC_DRAW_BLACK);CHKERRQ(ierr); 506 for (i=0; i<dim; i++) { 507 cl = (lg->colors ? lg->colors[i] : i + 1); 508 ierr = PetscDrawLine(draw,xr - (mlen + 6.7)*tw,yr - (4 + i)*th,xr - (mlen + 3.2)*tw,yr - (4 + i)*th,cl);CHKERRQ(ierr); 509 ierr = PetscDrawString(draw,xr - (mlen + 3)*tw,yr - (4.5 + i)*th,PETSC_DRAW_BLACK,lg->legend[i]);CHKERRQ(ierr); 510 } 511 ierr = PetscDrawLine(draw,xr - 2*tw,yr - 3*th,xr - 2*tw,yr - (4+lg->dim)*th,PETSC_DRAW_BLACK);CHKERRQ(ierr); 512 ierr = PetscDrawLine(draw,xr - (mlen + 8)*tw,yr - (4+lg->dim)*th,xr - 2*tw,yr - (4+lg->dim)*th,PETSC_DRAW_BLACK);CHKERRQ(ierr); 513 } 514 ierr = PetscDrawFlush(lg->win);CHKERRQ(ierr); 515 ierr = PetscDrawPause(lg->win);CHKERRQ(ierr); 516 #if defined(PETSC_HAVE_SETJMP_H) && defined(PETSC_HAVE_X) 517 XSetIOErrorHandler(PETSC_NULL); 518 #endif 519 PetscFunctionReturn(0); 520 } 521 522 #undef __FUNCT__ 523 #define __FUNCT__ "PetscDrawLGPrint" 524 /*@ 525 PetscDrawLGPrint - Prints a line graph. 526 527 Not collective 528 529 Input Parameter: 530 . lg - the line graph context 531 532 Level: beginner 533 534 Contributed by Matthew Knepley 535 536 .keywords: draw, line, graph 537 @*/ 538 PetscErrorCode PetscDrawLGPrint(PetscDrawLG lg) 539 { 540 PetscReal xmin=lg->xmin, xmax=lg->xmax, ymin=lg->ymin, ymax=lg->ymax; 541 int i, j, dim = lg->dim, nopts = lg->nopts; 542 543 PetscFunctionBegin; 544 if (lg && ((PetscObject)lg)->classid == PETSC_DRAW_CLASSID) PetscFunctionReturn(0); 545 PetscValidHeaderSpecific(lg, PETSC_DRAWLG_CLASSID,1); 546 if (nopts < 1) PetscFunctionReturn(0); 547 if (xmin > xmax || ymin > ymax) PetscFunctionReturn(0); 548 549 for (i = 0; i < dim; i++) { 550 PetscPrintf(((PetscObject)lg)->comm, "Line %d>\n", i); 551 for (j = 0; j < nopts; j++) { 552 PetscPrintf(((PetscObject)lg)->comm, " X: %g Y: %g\n", (double)lg->x[j*dim+i], (double)lg->y[j*dim+i]); 553 } 554 } 555 PetscFunctionReturn(0); 556 } 557