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,"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 <X11/Xlib.h> 429 #include <X11/Xutil.h> 430 #include <setjmp.h> 431 static jmp_buf PetscXIOErrorJumpBuf; 432 static void PetscXIOHandler(Display *dpy) 433 { 434 longjmp(PetscXIOErrorJumpBuf, 1); 435 } 436 #endif 437 438 #undef __FUNCT__ 439 #define __FUNCT__ "PetscDrawLGDraw" 440 /*@ 441 PetscDrawLGDraw - Redraws a line graph. 442 443 Not Collective,but ignored by all processors except processor 0 in PetscDrawLG 444 445 Input Parameter: 446 . lg - the line graph context 447 448 Level: intermediate 449 450 .seealso: PetscDrawSPDraw(), PetscDrawLGSPDraw() 451 452 @*/ 453 PetscErrorCode PetscDrawLGDraw(PetscDrawLG lg) 454 { 455 PetscReal xmin=lg->xmin,xmax=lg->xmax,ymin=lg->ymin,ymax=lg->ymax; 456 PetscErrorCode ierr; 457 int i,j,dim = lg->dim,nopts = lg->nopts,rank,cl; 458 PetscDraw draw = lg->win; 459 PetscBool isnull; 460 461 PetscFunctionBegin; 462 if (lg && ((PetscObject)lg)->classid == PETSC_DRAW_CLASSID) PetscFunctionReturn(0); 463 PetscValidHeaderSpecific(lg,PETSC_DRAWLG_CLASSID,1); 464 ierr = PetscDrawIsNull(lg->win,&isnull);CHKERRQ(ierr); 465 if (isnull) PetscFunctionReturn(0); 466 467 #if defined(PETSC_HAVE_SETJMP_H) && defined(PETSC_HAVE_X) 468 if (!setjmp(PetscXIOErrorJumpBuf)) XSetIOErrorHandler((XIOErrorHandler)PetscXIOHandler); 469 else { 470 XSetIOErrorHandler(NULL); 471 ierr = PetscDrawSetType(draw,PETSC_DRAW_NULL);CHKERRQ(ierr); 472 PetscFunctionReturn(0); 473 } 474 #endif 475 476 ierr = PetscDrawCheckResizedWindow(draw);CHKERRQ(ierr); 477 ierr = PetscDrawClear(draw);CHKERRQ(ierr); 478 ierr = PetscDrawAxisSetLimits(lg->axis,xmin,xmax,ymin,ymax);CHKERRQ(ierr); 479 ierr = PetscDrawAxisDraw(lg->axis);CHKERRQ(ierr); 480 481 ierr = MPI_Comm_rank(((PetscObject)lg)->comm,&rank);CHKERRQ(ierr); 482 if (!rank) { 483 484 for (i=0; i<dim; i++) { 485 for (j=1; j<nopts; j++) { 486 if (lg->colors) cl = lg->colors[i]; 487 else cl = PETSC_DRAW_BLACK+i; 488 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); 489 if (lg->use_dots) { 490 ierr = PetscDrawString(draw,lg->x[j*dim+i],lg->y[j*dim+i],cl,"x");CHKERRQ(ierr); 491 } 492 } 493 } 494 } 495 if (lg->legend) { 496 PetscReal xl,yl,xr,yr,tw,th; 497 size_t len,mlen = 0; 498 int cl; 499 ierr = PetscDrawGetCoordinates(draw,&xl,&yl,&xr,&yr);CHKERRQ(ierr); 500 ierr = PetscDrawStringGetSize(draw,&tw,&th);CHKERRQ(ierr); 501 for (i=0; i<dim; i++) { 502 ierr = PetscStrlen(lg->legend[i],&len);CHKERRQ(ierr); 503 mlen = PetscMax(mlen,len); 504 } 505 ierr = PetscDrawLine(draw,xr - (mlen + 8)*tw,yr - 3*th,xr - 2*tw,yr - 3*th,PETSC_DRAW_BLACK);CHKERRQ(ierr); 506 ierr = PetscDrawLine(draw,xr - (mlen + 8)*tw,yr - 3*th,xr - (mlen + 8)*tw,yr - (4+lg->dim)*th,PETSC_DRAW_BLACK);CHKERRQ(ierr); 507 for (i=0; i<dim; i++) { 508 cl = (lg->colors ? lg->colors[i] : i + 1); 509 ierr = PetscDrawLine(draw,xr - (mlen + 6.7)*tw,yr - (4 + i)*th,xr - (mlen + 3.2)*tw,yr - (4 + i)*th,cl);CHKERRQ(ierr); 510 ierr = PetscDrawString(draw,xr - (mlen + 3)*tw,yr - (4.5 + i)*th,PETSC_DRAW_BLACK,lg->legend[i]);CHKERRQ(ierr); 511 } 512 ierr = PetscDrawLine(draw,xr - 2*tw,yr - 3*th,xr - 2*tw,yr - (4+lg->dim)*th,PETSC_DRAW_BLACK);CHKERRQ(ierr); 513 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); 514 } 515 ierr = PetscDrawFlush(lg->win);CHKERRQ(ierr); 516 ierr = PetscDrawPause(lg->win);CHKERRQ(ierr); 517 #if defined(PETSC_HAVE_SETJMP_H) && defined(PETSC_HAVE_X) 518 XSetIOErrorHandler(NULL); 519 #endif 520 PetscFunctionReturn(0); 521 } 522 523 #undef __FUNCT__ 524 #define __FUNCT__ "PetscDrawLGPrint" 525 /*@ 526 PetscDrawLGPrint - Prints a line graph. 527 528 Not collective 529 530 Input Parameter: 531 . lg - the line graph context 532 533 Level: beginner 534 535 Contributed by Matthew Knepley 536 537 .keywords: draw, line, graph 538 @*/ 539 PetscErrorCode PetscDrawLGPrint(PetscDrawLG lg) 540 { 541 PetscReal xmin=lg->xmin, xmax=lg->xmax, ymin=lg->ymin, ymax=lg->ymax; 542 int i, j, dim = lg->dim, nopts = lg->nopts; 543 544 PetscFunctionBegin; 545 if (lg && ((PetscObject)lg)->classid == PETSC_DRAW_CLASSID) PetscFunctionReturn(0); 546 PetscValidHeaderSpecific(lg, PETSC_DRAWLG_CLASSID,1); 547 if (nopts < 1) PetscFunctionReturn(0); 548 if (xmin > xmax || ymin > ymax) PetscFunctionReturn(0); 549 550 for (i = 0; i < dim; i++) { 551 PetscPrintf(((PetscObject)lg)->comm, "Line %d>\n", i); 552 for (j = 0; j < nopts; j++) { 553 PetscPrintf(((PetscObject)lg)->comm, " X: %g Y: %g\n", (double)lg->x[j*dim+i], (double)lg->y[j*dim+i]); 554 } 555 } 556 PetscFunctionReturn(0); 557 } 558