1 #include <petscviewer.h> 2 #include <petsc/private/drawimpl.h> /*I "petscdraw.h" I*/ 3 PetscClassId PETSC_DRAWLG_CLASSID = 0; 4 5 /*@ 6 PetscDrawLGGetAxis - Gets the axis context associated with a line graph. 7 This is useful if one wants to change some axis property, such as 8 labels, color, etc. The axis context should not be destroyed by the 9 application code. 10 11 Not Collective, if lg is parallel then axis is parallel 12 13 Input Parameter: 14 . lg - the line graph context 15 16 Output Parameter: 17 . axis - the axis context 18 19 Level: advanced 20 21 .seealso: `PetscDrawLGCreate()`, `PetscDrawAxis`, `PetscDrawLG` 22 @*/ 23 PetscErrorCode PetscDrawLGGetAxis(PetscDrawLG lg, PetscDrawAxis *axis) 24 { 25 PetscFunctionBegin; 26 PetscValidHeaderSpecific(lg, PETSC_DRAWLG_CLASSID, 1); 27 PetscAssertPointer(axis, 2); 28 *axis = lg->axis; 29 PetscFunctionReturn(PETSC_SUCCESS); 30 } 31 32 /*@ 33 PetscDrawLGGetDraw - Gets the draw context associated with a line graph. 34 35 Not Collective, if lg is parallel then draw is parallel 36 37 Input Parameter: 38 . lg - the line graph context 39 40 Output Parameter: 41 . draw - the draw context 42 43 Level: intermediate 44 45 .seealso: `PetscDrawLGCreate()`, `PetscDraw`, `PetscDrawLG` 46 @*/ 47 PetscErrorCode PetscDrawLGGetDraw(PetscDrawLG lg, PetscDraw *draw) 48 { 49 PetscFunctionBegin; 50 PetscValidHeaderSpecific(lg, PETSC_DRAWLG_CLASSID, 1); 51 PetscAssertPointer(draw, 2); 52 *draw = lg->win; 53 PetscFunctionReturn(PETSC_SUCCESS); 54 } 55 56 /*@ 57 PetscDrawLGSPDraw - Redraws a line graph and a scatter plot on the same `PetscDraw` they must share 58 59 Collective 60 61 Input Parameters: 62 + lg - the line graph context 63 - spin - the scatter plot 64 65 Level: intermediate 66 67 Developer Notes: 68 This code cheats and uses the fact that the `PetscDrawLG` and `PetscDrawSP` structs are the same 69 70 .seealso: `PetscDrawLGDraw()`, `PetscDrawSPDraw()` 71 @*/ 72 PetscErrorCode PetscDrawLGSPDraw(PetscDrawLG lg, PetscDrawSP spin) 73 { 74 PetscDrawLG sp = (PetscDrawLG)spin; 75 PetscReal xmin, xmax, ymin, ymax; 76 PetscBool isnull; 77 PetscMPIInt rank; 78 PetscDraw draw; 79 80 PetscFunctionBegin; 81 PetscValidHeaderSpecific(lg, PETSC_DRAWLG_CLASSID, 1); 82 PetscValidHeaderSpecific(sp, PETSC_DRAWLG_CLASSID, 2); 83 PetscCall(PetscDrawIsNull(lg->win, &isnull)); 84 if (isnull) PetscFunctionReturn(PETSC_SUCCESS); 85 PetscCallMPI(MPI_Comm_rank(PetscObjectComm((PetscObject)lg), &rank)); 86 87 draw = lg->win; 88 PetscCall(PetscDrawCheckResizedWindow(draw)); 89 PetscCall(PetscDrawClear(draw)); 90 91 xmin = PetscMin(lg->xmin, sp->xmin); 92 ymin = PetscMin(lg->ymin, sp->ymin); 93 xmax = PetscMax(lg->xmax, sp->xmax); 94 ymax = PetscMax(lg->ymax, sp->ymax); 95 PetscCall(PetscDrawAxisSetLimits(lg->axis, xmin, xmax, ymin, ymax)); 96 PetscCall(PetscDrawAxisDraw(lg->axis)); 97 98 PetscDrawCollectiveBegin(draw); 99 if (rank == 0) { 100 int i, j, dim, nopts; 101 dim = lg->dim; 102 nopts = lg->nopts; 103 for (i = 0; i < dim; i++) { 104 for (j = 1; j < nopts; j++) { 105 PetscCall(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)); 106 if (lg->use_markers) PetscCall(PetscDrawMarker(draw, lg->x[j * dim + i], lg->y[j * dim + i], PETSC_DRAW_RED)); 107 } 108 } 109 dim = sp->dim; 110 nopts = sp->nopts; 111 for (i = 0; i < dim; i++) { 112 for (j = 0; j < nopts; j++) PetscCall(PetscDrawMarker(draw, sp->x[j * dim + i], sp->y[j * dim + i], PETSC_DRAW_RED)); 113 } 114 } 115 PetscDrawCollectiveEnd(draw); 116 117 PetscCall(PetscDrawFlush(draw)); 118 PetscCall(PetscDrawPause(draw)); 119 PetscFunctionReturn(PETSC_SUCCESS); 120 } 121 122 /*@ 123 PetscDrawLGCreate - Creates a line graph data structure. 124 125 Collective 126 127 Input Parameters: 128 + draw - the window where the graph will be made. 129 - dim - the number of curves which will be drawn 130 131 Output Parameter: 132 . outlg - the line graph context 133 134 Level: intermediate 135 136 Notes: 137 The MPI communicator that owns the `PetscDraw` owns this `PetscDrawLG`, but the calls to set options and add points are ignored on all processes except the 138 zeroth MPI process in the communicator. 139 140 All MPI ranks in the communicator must call `PetscDrawLGDraw()` to display the updated graph. 141 142 .seealso: `PetscDrawLGDestroy()`, `PetscDrawLGAddPoint()`, `PetscDrawLGAddCommonPoint()`, `PetscDrawLGAddPoints()`, `PetscDrawLGDraw()`, `PetscDrawLGSave()`, 143 `PetscDrawLGView()`, `PetscDrawLGReset()`, `PetscDrawLGSetDimension()`, `PetscDrawLGGetDimension()`, `PetscDrawLGSetLegend()`, `PetscDrawLGGetAxis()`, 144 `PetscDrawLGGetDraw()`, `PetscDrawLGSetUseMarkers()`, `PetscDrawLGSetLimits()`, `PetscDrawLGSetColors()`, `PetscDrawLGSetOptionsPrefix()`, `PetscDrawLGSetFromOptions()` 145 @*/ 146 PetscErrorCode PetscDrawLGCreate(PetscDraw draw, PetscInt dim, PetscDrawLG *outlg) 147 { 148 PetscDrawLG lg; 149 150 PetscFunctionBegin; 151 PetscValidHeaderSpecific(draw, PETSC_DRAW_CLASSID, 1); 152 PetscValidLogicalCollectiveInt(draw, dim, 2); 153 PetscAssertPointer(outlg, 3); 154 155 PetscCall(PetscHeaderCreate(lg, PETSC_DRAWLG_CLASSID, "DrawLG", "Line Graph", "Draw", PetscObjectComm((PetscObject)draw), PetscDrawLGDestroy, NULL)); 156 PetscCall(PetscDrawLGSetOptionsPrefix(lg, ((PetscObject)draw)->prefix)); 157 158 PetscCall(PetscObjectReference((PetscObject)draw)); 159 lg->win = draw; 160 161 lg->view = NULL; 162 lg->destroy = NULL; 163 lg->nopts = 0; 164 lg->dim = (int)dim; 165 lg->xmin = 1.e20; 166 lg->ymin = 1.e20; 167 lg->xmax = -1.e20; 168 lg->ymax = -1.e20; 169 170 PetscCall(PetscMalloc2(dim * PETSC_DRAW_LG_CHUNK_SIZE, &lg->x, dim * PETSC_DRAW_LG_CHUNK_SIZE, &lg->y)); 171 172 lg->len = (int)(dim * PETSC_DRAW_LG_CHUNK_SIZE); 173 lg->loc = 0; 174 lg->use_markers = PETSC_FALSE; 175 176 PetscCall(PetscDrawAxisCreate(draw, &lg->axis)); 177 178 *outlg = lg; 179 PetscFunctionReturn(PETSC_SUCCESS); 180 } 181 182 /*@ 183 PetscDrawLGSetColors - Sets the color of each line graph drawn 184 185 Logically Collective 186 187 Input Parameters: 188 + lg - the line graph context. 189 - colors - the colors 190 191 Level: intermediate 192 193 .seealso: `PetscDrawLG`, `PetscDrawLGCreate()` 194 @*/ 195 PetscErrorCode PetscDrawLGSetColors(PetscDrawLG lg, const int colors[]) 196 { 197 PetscFunctionBegin; 198 PetscValidHeaderSpecific(lg, PETSC_DRAWLG_CLASSID, 1); 199 if (lg->dim) PetscAssertPointer(colors, 2); 200 201 PetscCall(PetscFree(lg->colors)); 202 PetscCall(PetscMalloc1(lg->dim, &lg->colors)); 203 PetscCall(PetscArraycpy(lg->colors, colors, lg->dim)); 204 PetscFunctionReturn(PETSC_SUCCESS); 205 } 206 207 /*@C 208 PetscDrawLGSetLegend - sets the names of each curve plotted 209 210 Logically Collective 211 212 Input Parameters: 213 + lg - the line graph context. 214 - names - the names for each curve 215 216 Level: intermediate 217 218 Note: 219 Call `PetscDrawLGGetAxis()` and then change properties of the `PetscDrawAxis` for detailed control of the plot 220 221 .seealso: `PetscDrawLGGetAxis()`, `PetscDrawAxis`, `PetscDrawAxisSetColors()`, `PetscDrawAxisSetLabels()`, `PetscDrawAxisSetHoldLimits()` 222 @*/ 223 PetscErrorCode PetscDrawLGSetLegend(PetscDrawLG lg, const char *const names[]) 224 { 225 PetscInt i; 226 227 PetscFunctionBegin; 228 PetscValidHeaderSpecific(lg, PETSC_DRAWLG_CLASSID, 1); 229 if (names) PetscAssertPointer(names, 2); 230 231 if (lg->legend) { 232 for (i = 0; i < lg->dim; i++) PetscCall(PetscFree(lg->legend[i])); 233 PetscCall(PetscFree(lg->legend)); 234 } 235 if (names) { 236 PetscCall(PetscMalloc1(lg->dim, &lg->legend)); 237 for (i = 0; i < lg->dim; i++) PetscCall(PetscStrallocpy(names[i], &lg->legend[i])); 238 } 239 PetscFunctionReturn(PETSC_SUCCESS); 240 } 241 242 /*@ 243 PetscDrawLGGetDimension - Get the number of curves that are to be drawn. 244 245 Not Collective 246 247 Input Parameter: 248 . lg - the line graph context. 249 250 Output Parameter: 251 . dim - the number of curves. 252 253 Level: intermediate 254 255 .seealso: `PetscDrawLGC`, `PetscDrawLGCreate()`, `PetscDrawLGSetDimension()` 256 @*/ 257 PetscErrorCode PetscDrawLGGetDimension(PetscDrawLG lg, PetscInt *dim) 258 { 259 PetscFunctionBegin; 260 PetscValidHeaderSpecific(lg, PETSC_DRAWLG_CLASSID, 1); 261 PetscAssertPointer(dim, 2); 262 *dim = lg->dim; 263 PetscFunctionReturn(PETSC_SUCCESS); 264 } 265 266 /*@ 267 PetscDrawLGSetDimension - Change the number of curves that are to be drawn. 268 269 Logically Collective 270 271 Input Parameters: 272 + lg - the line graph context. 273 - dim - the number of curves. 274 275 Level: intermediate 276 277 .seealso: `PetscDrawLGCreate()`, `PetscDrawLGGetDimension()` 278 @*/ 279 PetscErrorCode PetscDrawLGSetDimension(PetscDrawLG lg, PetscInt dim) 280 { 281 PetscInt i; 282 283 PetscFunctionBegin; 284 PetscValidHeaderSpecific(lg, PETSC_DRAWLG_CLASSID, 1); 285 PetscValidLogicalCollectiveInt(lg, dim, 2); 286 if (lg->dim == dim) PetscFunctionReturn(PETSC_SUCCESS); 287 288 PetscCall(PetscFree2(lg->x, lg->y)); 289 if (lg->legend) { 290 for (i = 0; i < lg->dim; i++) PetscCall(PetscFree(lg->legend[i])); 291 PetscCall(PetscFree(lg->legend)); 292 } 293 PetscCall(PetscFree(lg->colors)); 294 lg->dim = (int)dim; 295 PetscCall(PetscMalloc2(dim * PETSC_DRAW_LG_CHUNK_SIZE, &lg->x, dim * PETSC_DRAW_LG_CHUNK_SIZE, &lg->y)); 296 lg->len = (int)(dim * PETSC_DRAW_LG_CHUNK_SIZE); 297 PetscFunctionReturn(PETSC_SUCCESS); 298 } 299 300 /*@ 301 PetscDrawLGSetLimits - Sets the axis limits for a line graph. If more 302 points are added after this call, the limits will be adjusted to 303 include those additional points. 304 305 Logically Collective 306 307 Input Parameters: 308 + lg - the line graph context 309 . x_min - the horizontal lower limit 310 . x_max - the horizontal upper limit 311 . y_min - the vertical lower limit 312 - y_max - the vertical upper limit 313 314 Level: intermediate 315 316 .seealso: `PetscDrawLGCreate()`, `PetscDrawLG`, `PetscDrawAxis` 317 @*/ 318 PetscErrorCode PetscDrawLGSetLimits(PetscDrawLG lg, PetscReal x_min, PetscReal x_max, PetscReal y_min, PetscReal y_max) 319 { 320 PetscFunctionBegin; 321 PetscValidHeaderSpecific(lg, PETSC_DRAWLG_CLASSID, 1); 322 323 (lg)->xmin = x_min; 324 (lg)->xmax = x_max; 325 (lg)->ymin = y_min; 326 (lg)->ymax = y_max; 327 PetscFunctionReturn(PETSC_SUCCESS); 328 } 329 330 /*@ 331 PetscDrawLGReset - Clears line graph to allow for reuse with new data. 332 333 Logically Collective 334 335 Input Parameter: 336 . lg - the line graph context. 337 338 Level: intermediate 339 340 .seealso: `PetscDrawLG`, `PetscDrawLGCreate()` 341 @*/ 342 PetscErrorCode PetscDrawLGReset(PetscDrawLG lg) 343 { 344 PetscFunctionBegin; 345 PetscValidHeaderSpecific(lg, PETSC_DRAWLG_CLASSID, 1); 346 lg->xmin = 1.e20; 347 lg->ymin = 1.e20; 348 lg->xmax = -1.e20; 349 lg->ymax = -1.e20; 350 lg->loc = 0; 351 lg->nopts = 0; 352 PetscFunctionReturn(PETSC_SUCCESS); 353 } 354 355 /*@ 356 PetscDrawLGDestroy - Frees all space taken up by line graph data structure. 357 358 Collective 359 360 Input Parameter: 361 . lg - the line graph context 362 363 Level: intermediate 364 365 .seealso: `PetscDrawLG`, `PetscDrawLGCreate()` 366 @*/ 367 PetscErrorCode PetscDrawLGDestroy(PetscDrawLG *lg) 368 { 369 PetscInt i; 370 371 PetscFunctionBegin; 372 if (!*lg) PetscFunctionReturn(PETSC_SUCCESS); 373 PetscValidHeaderSpecific(*lg, PETSC_DRAWLG_CLASSID, 1); 374 if (--((PetscObject)*lg)->refct > 0) { 375 *lg = NULL; 376 PetscFunctionReturn(PETSC_SUCCESS); 377 } 378 379 if ((*lg)->legend) { 380 for (i = 0; i < (*lg)->dim; i++) PetscCall(PetscFree((*lg)->legend[i])); 381 PetscCall(PetscFree((*lg)->legend)); 382 } 383 PetscCall(PetscFree((*lg)->colors)); 384 PetscCall(PetscFree2((*lg)->x, (*lg)->y)); 385 PetscCall(PetscDrawAxisDestroy(&(*lg)->axis)); 386 PetscCall(PetscDrawDestroy(&(*lg)->win)); 387 PetscCall(PetscHeaderDestroy(lg)); 388 PetscFunctionReturn(PETSC_SUCCESS); 389 } 390 /*@ 391 PetscDrawLGSetUseMarkers - Causes the line graph object to draw a marker for each data-point. 392 393 Logically Collective 394 395 Input Parameters: 396 + lg - the linegraph context 397 - flg - should mark each data point 398 399 Options Database Key: 400 . -lg_use_markers <true,false> - true means it draws a marker for each point 401 402 Level: intermediate 403 404 .seealso: `PetscDrawLG`, `PetscDrawLGCreate()` 405 @*/ 406 PetscErrorCode PetscDrawLGSetUseMarkers(PetscDrawLG lg, PetscBool flg) 407 { 408 PetscFunctionBegin; 409 PetscValidHeaderSpecific(lg, PETSC_DRAWLG_CLASSID, 1); 410 PetscValidLogicalCollectiveBool(lg, flg, 2); 411 lg->use_markers = flg; 412 PetscFunctionReturn(PETSC_SUCCESS); 413 } 414 415 /*@ 416 PetscDrawLGDraw - Redraws a line graph. 417 418 Collective 419 420 Input Parameter: 421 . lg - the line graph context 422 423 Level: intermediate 424 425 .seealso: `PetscDrawLG`, `PetscDrawSPDraw()`, `PetscDrawLGSPDraw()`, `PetscDrawLGReset()` 426 @*/ 427 PetscErrorCode PetscDrawLGDraw(PetscDrawLG lg) 428 { 429 PetscReal xmin, xmax, ymin, ymax; 430 PetscMPIInt rank; 431 PetscDraw draw; 432 PetscBool isnull; 433 434 PetscFunctionBegin; 435 PetscValidHeaderSpecific(lg, PETSC_DRAWLG_CLASSID, 1); 436 PetscCall(PetscDrawIsNull(lg->win, &isnull)); 437 if (isnull) PetscFunctionReturn(PETSC_SUCCESS); 438 PetscCallMPI(MPI_Comm_rank(PetscObjectComm((PetscObject)lg), &rank)); 439 440 draw = lg->win; 441 PetscCall(PetscDrawCheckResizedWindow(draw)); 442 PetscCall(PetscDrawClear(draw)); 443 444 xmin = lg->xmin; 445 xmax = lg->xmax; 446 ymin = lg->ymin; 447 ymax = lg->ymax; 448 PetscCall(PetscDrawAxisSetLimits(lg->axis, xmin, xmax, ymin, ymax)); 449 PetscCall(PetscDrawAxisDraw(lg->axis)); 450 451 PetscDrawCollectiveBegin(draw); 452 if (rank == 0) { 453 int i, j, dim = lg->dim, nopts = lg->nopts, cl; 454 for (i = 0; i < dim; i++) { 455 for (j = 1; j < nopts; j++) { 456 cl = lg->colors ? lg->colors[i] : ((PETSC_DRAW_BLACK + i) % PETSC_DRAW_MAXCOLOR); 457 PetscCall(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)); 458 if (lg->use_markers) PetscCall(PetscDrawMarker(draw, lg->x[j * dim + i], lg->y[j * dim + i], cl)); 459 } 460 } 461 } 462 if (rank == 0 && lg->legend) { 463 PetscBool right = PETSC_FALSE; 464 int i, dim = lg->dim, cl; 465 PetscReal xl, yl, xr, yr, tw, th; 466 size_t slen, len = 0; 467 468 PetscCall(PetscDrawAxisGetLimits(lg->axis, &xl, &xr, &yl, &yr)); 469 PetscCall(PetscDrawStringGetSize(draw, &tw, &th)); 470 for (i = 0; i < dim; i++) { 471 PetscCall(PetscStrlen(lg->legend[i], &slen)); 472 len = PetscMax(len, slen); 473 } 474 if (right) { 475 xr = xr - 1.5 * tw; 476 xl = xr - ((PetscReal)len + 7) * tw; 477 } else { 478 xl = xl + 1.5 * tw; 479 xr = xl + ((PetscReal)len + 7) * tw; 480 } 481 yr = yr - 1.0 * th; 482 yl = yr - (dim + 1) * th; 483 PetscCall(PetscDrawLine(draw, xl, yl, xr, yl, PETSC_DRAW_BLACK)); 484 PetscCall(PetscDrawLine(draw, xr, yl, xr, yr, PETSC_DRAW_BLACK)); 485 PetscCall(PetscDrawLine(draw, xr, yr, xl, yr, PETSC_DRAW_BLACK)); 486 PetscCall(PetscDrawLine(draw, xl, yr, xl, yl, PETSC_DRAW_BLACK)); 487 for (i = 0; i < dim; i++) { 488 cl = lg->colors ? lg->colors[i] : (PETSC_DRAW_BLACK + i); 489 PetscCall(PetscDrawLine(draw, xl + 1 * tw, yr - (i + 1) * th, xl + 5 * tw, yr - (i + 1) * th, cl)); 490 PetscCall(PetscDrawString(draw, xl + 6 * tw, yr - (i + 1.5) * th, PETSC_DRAW_BLACK, lg->legend[i])); 491 } 492 } 493 PetscDrawCollectiveEnd(draw); 494 495 PetscCall(PetscDrawFlush(draw)); 496 PetscCall(PetscDrawPause(draw)); 497 PetscFunctionReturn(PETSC_SUCCESS); 498 } 499 500 /*@ 501 PetscDrawLGSave - Saves a drawn image 502 503 Collective 504 505 Input Parameter: 506 . lg - The line graph context 507 508 Level: intermediate 509 510 .seealso: `PetscDrawLG`, `PetscDrawSave()`, `PetscDrawLGCreate()`, `PetscDrawLGGetDraw()`, `PetscDrawSetSave()` 511 @*/ 512 PetscErrorCode PetscDrawLGSave(PetscDrawLG lg) 513 { 514 PetscFunctionBegin; 515 PetscValidHeaderSpecific(lg, PETSC_DRAWLG_CLASSID, 1); 516 PetscCall(PetscDrawSave(lg->win)); 517 PetscFunctionReturn(PETSC_SUCCESS); 518 } 519 520 /*@ 521 PetscDrawLGView - Prints a line graph. 522 523 Collective 524 525 Input Parameters: 526 + lg - the line graph context 527 - viewer - the viewer to view it with 528 529 Level: beginner 530 531 .seealso: `PetscDrawLG`, `PetscDrawLGCreate()` 532 @*/ 533 PetscErrorCode PetscDrawLGView(PetscDrawLG lg, PetscViewer viewer) 534 { 535 PetscReal xmin = lg->xmin, xmax = lg->xmax, ymin = lg->ymin, ymax = lg->ymax; 536 PetscInt i, j, dim = lg->dim, nopts = lg->nopts; 537 538 PetscFunctionBegin; 539 PetscValidHeaderSpecific(lg, PETSC_DRAWLG_CLASSID, 1); 540 541 if (nopts < 1) PetscFunctionReturn(PETSC_SUCCESS); 542 if (xmin > xmax || ymin > ymax) PetscFunctionReturn(PETSC_SUCCESS); 543 544 if (!viewer) PetscCall(PetscViewerASCIIGetStdout(PetscObjectComm((PetscObject)lg), &viewer)); 545 PetscCall(PetscObjectPrintClassNamePrefixType((PetscObject)lg, viewer)); 546 for (i = 0; i < dim; i++) { 547 PetscCall(PetscViewerASCIIPrintf(viewer, "Line %" PetscInt_FMT ">\n", i)); 548 for (j = 0; j < nopts; j++) PetscCall(PetscViewerASCIIPrintf(viewer, " X: %g Y: %g\n", (double)lg->x[j * dim + i], (double)lg->y[j * dim + i])); 549 } 550 PetscFunctionReturn(PETSC_SUCCESS); 551 } 552 553 /*@ 554 PetscDrawLGSetOptionsPrefix - Sets the prefix used for searching for all 555 `PetscDrawLG` options in the database. 556 557 Logically Collective 558 559 Input Parameters: 560 + lg - the line graph context 561 - prefix - the prefix to prepend to all option names 562 563 Level: advanced 564 565 .seealso: `PetscDrawLG`, `PetscDrawLGSetFromOptions()`, `PetscDrawLGCreate()` 566 @*/ 567 PetscErrorCode PetscDrawLGSetOptionsPrefix(PetscDrawLG lg, const char prefix[]) 568 { 569 PetscFunctionBegin; 570 PetscValidHeaderSpecific(lg, PETSC_DRAWLG_CLASSID, 1); 571 PetscCall(PetscObjectSetOptionsPrefix((PetscObject)lg, prefix)); 572 PetscFunctionReturn(PETSC_SUCCESS); 573 } 574 575 /*@ 576 PetscDrawLGSetFromOptions - Sets options related to the line graph object 577 578 Collective 579 580 Input Parameters: 581 . lg - the line graph context 582 583 Options Database Key: 584 . -lg_use_markers <true,false> - true means it draws a marker for each point 585 586 Level: intermediate 587 588 .seealso: `PetscDrawLG`, `PetscDrawLGDestroy()`, `PetscDrawLGCreate()` 589 @*/ 590 PetscErrorCode PetscDrawLGSetFromOptions(PetscDrawLG lg) 591 { 592 PetscBool usemarkers, set; 593 PetscDrawMarkerType markertype; 594 595 PetscFunctionBegin; 596 PetscValidHeaderSpecific(lg, PETSC_DRAWLG_CLASSID, 1); 597 598 PetscCall(PetscDrawGetMarkerType(lg->win, &markertype)); 599 PetscCall(PetscOptionsGetEnum(((PetscObject)lg)->options, ((PetscObject)lg)->prefix, "-lg_marker_type", PetscDrawMarkerTypes, (PetscEnum *)&markertype, &set)); 600 if (set) { 601 PetscCall(PetscDrawLGSetUseMarkers(lg, PETSC_TRUE)); 602 PetscCall(PetscDrawSetMarkerType(lg->win, markertype)); 603 } 604 usemarkers = lg->use_markers; 605 PetscCall(PetscOptionsGetBool(((PetscObject)lg)->options, ((PetscObject)lg)->prefix, "-lg_use_markers", &usemarkers, &set)); 606 if (set) PetscCall(PetscDrawLGSetUseMarkers(lg, usemarkers)); 607 PetscFunctionReturn(PETSC_SUCCESS); 608 } 609