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