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 = 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 = 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 = dim; 295 PetscCall(PetscMalloc2(dim * PETSC_DRAW_LG_CHUNK_SIZE, &lg->x, dim * PETSC_DRAW_LG_CHUNK_SIZE, &lg->y)); 296 lg->len = 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 PetscCall(PetscDrawAxisGetLimits(lg->axis, &xl, &xr, &yl, &yr)); 468 PetscCall(PetscDrawStringGetSize(draw, &tw, &th)); 469 for (i = 0; i < dim; i++) { 470 PetscCall(PetscStrlen(lg->legend[i], &slen)); 471 len = PetscMax(len, slen); 472 } 473 if (right) { 474 xr = xr - 1.5 * tw; 475 xl = xr - (len + 7) * tw; 476 } else { 477 xl = xl + 1.5 * tw; 478 xr = xl + (len + 7) * tw; 479 } 480 yr = yr - 1.0 * th; 481 yl = yr - (dim + 1) * th; 482 PetscCall(PetscDrawLine(draw, xl, yl, xr, yl, PETSC_DRAW_BLACK)); 483 PetscCall(PetscDrawLine(draw, xr, yl, xr, yr, PETSC_DRAW_BLACK)); 484 PetscCall(PetscDrawLine(draw, xr, yr, xl, yr, PETSC_DRAW_BLACK)); 485 PetscCall(PetscDrawLine(draw, xl, yr, xl, yl, PETSC_DRAW_BLACK)); 486 for (i = 0; i < dim; i++) { 487 cl = lg->colors ? lg->colors[i] : (PETSC_DRAW_BLACK + i); 488 PetscCall(PetscDrawLine(draw, xl + 1 * tw, yr - (i + 1) * th, xl + 5 * tw, yr - (i + 1) * th, cl)); 489 PetscCall(PetscDrawString(draw, xl + 6 * tw, yr - (i + 1.5) * th, PETSC_DRAW_BLACK, lg->legend[i])); 490 } 491 } 492 PetscDrawCollectiveEnd(draw); 493 494 PetscCall(PetscDrawFlush(draw)); 495 PetscCall(PetscDrawPause(draw)); 496 PetscFunctionReturn(PETSC_SUCCESS); 497 } 498 499 /*@ 500 PetscDrawLGSave - Saves a drawn image 501 502 Collective 503 504 Input Parameter: 505 . lg - The line graph context 506 507 Level: intermediate 508 509 .seealso: `PetscDrawLG`, `PetscDrawSave()`, `PetscDrawLGCreate()`, `PetscDrawLGGetDraw()`, `PetscDrawSetSave()` 510 @*/ 511 PetscErrorCode PetscDrawLGSave(PetscDrawLG lg) 512 { 513 PetscFunctionBegin; 514 PetscValidHeaderSpecific(lg, PETSC_DRAWLG_CLASSID, 1); 515 PetscCall(PetscDrawSave(lg->win)); 516 PetscFunctionReturn(PETSC_SUCCESS); 517 } 518 519 /*@ 520 PetscDrawLGView - Prints a line graph. 521 522 Collective 523 524 Input Parameters: 525 + lg - the line graph context 526 - viewer - the viewer to view it with 527 528 Level: beginner 529 530 .seealso: `PetscDrawLG`, `PetscDrawLGCreate()` 531 @*/ 532 PetscErrorCode PetscDrawLGView(PetscDrawLG lg, PetscViewer viewer) 533 { 534 PetscReal xmin = lg->xmin, xmax = lg->xmax, ymin = lg->ymin, ymax = lg->ymax; 535 PetscInt i, j, dim = lg->dim, nopts = lg->nopts; 536 537 PetscFunctionBegin; 538 PetscValidHeaderSpecific(lg, PETSC_DRAWLG_CLASSID, 1); 539 540 if (nopts < 1) PetscFunctionReturn(PETSC_SUCCESS); 541 if (xmin > xmax || ymin > ymax) PetscFunctionReturn(PETSC_SUCCESS); 542 543 if (!viewer) PetscCall(PetscViewerASCIIGetStdout(PetscObjectComm((PetscObject)lg), &viewer)); 544 PetscCall(PetscObjectPrintClassNamePrefixType((PetscObject)lg, viewer)); 545 for (i = 0; i < dim; i++) { 546 PetscCall(PetscViewerASCIIPrintf(viewer, "Line %" PetscInt_FMT ">\n", i)); 547 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])); 548 } 549 PetscFunctionReturn(PETSC_SUCCESS); 550 } 551 552 /*@C 553 PetscDrawLGSetOptionsPrefix - Sets the prefix used for searching for all 554 `PetscDrawLG` options in the database. 555 556 Logically Collective 557 558 Input Parameters: 559 + lg - the line graph context 560 - prefix - the prefix to prepend to all option names 561 562 Level: advanced 563 564 .seealso: `PetscDrawLG`, `PetscDrawLGSetFromOptions()`, `PetscDrawLGCreate()` 565 @*/ 566 PetscErrorCode PetscDrawLGSetOptionsPrefix(PetscDrawLG lg, const char prefix[]) 567 { 568 PetscFunctionBegin; 569 PetscValidHeaderSpecific(lg, PETSC_DRAWLG_CLASSID, 1); 570 PetscCall(PetscObjectSetOptionsPrefix((PetscObject)lg, prefix)); 571 PetscFunctionReturn(PETSC_SUCCESS); 572 } 573 574 /*@ 575 PetscDrawLGSetFromOptions - Sets options related to the line graph object 576 577 Collective 578 579 Input Parameters: 580 . lg - the line graph context 581 582 Options Database Key: 583 . -lg_use_markers <true,false> - true means it draws a marker for each point 584 585 Level: intermediate 586 587 .seealso: `PetscDrawLG`, `PetscDrawLGDestroy()`, `PetscDrawLGCreate()` 588 @*/ 589 PetscErrorCode PetscDrawLGSetFromOptions(PetscDrawLG lg) 590 { 591 PetscBool usemarkers, set; 592 PetscDrawMarkerType markertype; 593 594 PetscFunctionBegin; 595 PetscValidHeaderSpecific(lg, PETSC_DRAWLG_CLASSID, 1); 596 597 PetscCall(PetscDrawGetMarkerType(lg->win, &markertype)); 598 PetscCall(PetscOptionsGetEnum(((PetscObject)lg)->options, ((PetscObject)lg)->prefix, "-lg_marker_type", PetscDrawMarkerTypes, (PetscEnum *)&markertype, &set)); 599 if (set) { 600 PetscCall(PetscDrawLGSetUseMarkers(lg, PETSC_TRUE)); 601 PetscCall(PetscDrawSetMarkerType(lg->win, markertype)); 602 } 603 usemarkers = lg->use_markers; 604 PetscCall(PetscOptionsGetBool(((PetscObject)lg)->options, ((PetscObject)lg)->prefix, "-lg_use_markers", &usemarkers, &set)); 605 if (set) PetscCall(PetscDrawLGSetUseMarkers(lg, usemarkers)); 606 PetscFunctionReturn(PETSC_SUCCESS); 607 } 608