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