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 PetscValidPointer(axis, 2); 29 *axis = lg->axis; 30 PetscFunctionReturn(0); 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 PetscValidPointer(draw, 2); 53 *draw = lg->win; 54 PetscFunctionReturn(0); 55 } 56 57 /*@ 58 PetscDrawLGSPDraw - Redraws a line graph and a scatter plot on the same `PetscDraw` they must share 59 60 Collective on lg 61 62 Input Parameters: 63 + lg - the line graph context 64 - spin - the scatter plot 65 66 Level: intermediate 67 68 Developer Note: 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(0); 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(0); 121 } 122 123 /*@ 124 PetscDrawLGCreate - Creates a line graph data structure. 125 126 Collective on draw 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 Parameters: 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: `PetscDrawLGCreate`, `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 PetscValidPointer(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(0); 181 } 182 183 /*@ 184 PetscDrawLGSetColors - Sets the color of each line graph drawn 185 186 Logically Collective on lg 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) PetscValidIntPointer(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(0); 206 } 207 208 /*@C 209 PetscDrawLGSetLegend - sets the names of each curve plotted 210 211 Logically Collective on lg 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) PetscValidPointer(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(0); 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 PetscValidIntPointer(dim, 2); 263 *dim = lg->dim; 264 PetscFunctionReturn(0); 265 } 266 267 /*@ 268 PetscDrawLGSetDimension - Change the number of curves that are to be drawn. 269 270 Logically Collective on lg 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(0); 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(0); 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 on lg 307 308 Input Parameters: 309 + xlg - the line graph context 310 - x_min,x_max,y_min,y_max - the limits 311 312 Level: intermediate 313 314 .seealso: `PetscDrawLGCreate()`, `PetscDrawLG`, `PetscDrawAxis` 315 @*/ 316 PetscErrorCode PetscDrawLGSetLimits(PetscDrawLG lg, PetscReal x_min, PetscReal x_max, PetscReal y_min, PetscReal y_max) 317 { 318 PetscFunctionBegin; 319 PetscValidHeaderSpecific(lg, PETSC_DRAWLG_CLASSID, 1); 320 321 (lg)->xmin = x_min; 322 (lg)->xmax = x_max; 323 (lg)->ymin = y_min; 324 (lg)->ymax = y_max; 325 PetscFunctionReturn(0); 326 } 327 328 /*@ 329 PetscDrawLGReset - Clears line graph to allow for reuse with new data. 330 331 Logically Collective on lg 332 333 Input Parameter: 334 . lg - the line graph context. 335 336 Level: intermediate 337 338 .seealso: `PetscDrawLG`, `PetscDrawLGCreate()` 339 @*/ 340 PetscErrorCode PetscDrawLGReset(PetscDrawLG lg) 341 { 342 PetscFunctionBegin; 343 PetscValidHeaderSpecific(lg, PETSC_DRAWLG_CLASSID, 1); 344 lg->xmin = 1.e20; 345 lg->ymin = 1.e20; 346 lg->xmax = -1.e20; 347 lg->ymax = -1.e20; 348 lg->loc = 0; 349 lg->nopts = 0; 350 PetscFunctionReturn(0); 351 } 352 353 /*@ 354 PetscDrawLGDestroy - Frees all space taken up by line graph data structure. 355 356 Collective on lg 357 358 Input Parameter: 359 . lg - the line graph context 360 361 Level: intermediate 362 363 .seealso: `PetscDrawLG`, `PetscDrawLGCreate()` 364 @*/ 365 PetscErrorCode PetscDrawLGDestroy(PetscDrawLG *lg) 366 { 367 PetscInt i; 368 369 PetscFunctionBegin; 370 if (!*lg) PetscFunctionReturn(0); 371 PetscValidHeaderSpecific(*lg, PETSC_DRAWLG_CLASSID, 1); 372 if (--((PetscObject)(*lg))->refct > 0) { 373 *lg = NULL; 374 PetscFunctionReturn(0); 375 } 376 377 if ((*lg)->legend) { 378 for (i = 0; i < (*lg)->dim; i++) PetscCall(PetscFree((*lg)->legend[i])); 379 PetscCall(PetscFree((*lg)->legend)); 380 } 381 PetscCall(PetscFree((*lg)->colors)); 382 PetscCall(PetscFree2((*lg)->x, (*lg)->y)); 383 PetscCall(PetscDrawAxisDestroy(&(*lg)->axis)); 384 PetscCall(PetscDrawDestroy(&(*lg)->win)); 385 PetscCall(PetscHeaderDestroy(lg)); 386 PetscFunctionReturn(0); 387 } 388 /*@ 389 PetscDrawLGSetUseMarkers - Causes the line graph object to draw a marker for each data-point. 390 391 Logically Collective on lg 392 393 Input Parameters: 394 + lg - the linegraph context 395 - flg - should mark each data point 396 397 Options Database Key: 398 . -lg_use_markers <true,false> - true means it draws a marker for each point 399 400 Level: intermediate 401 402 .seealso: `PetscDrawLG`, `PetscDrawLGCreate()` 403 @*/ 404 PetscErrorCode PetscDrawLGSetUseMarkers(PetscDrawLG lg, PetscBool flg) 405 { 406 PetscFunctionBegin; 407 PetscValidHeaderSpecific(lg, PETSC_DRAWLG_CLASSID, 1); 408 PetscValidLogicalCollectiveBool(lg, flg, 2); 409 lg->use_markers = flg; 410 PetscFunctionReturn(0); 411 } 412 413 /*@ 414 PetscDrawLGDraw - Redraws a line graph. 415 416 Collective on lg 417 418 Input Parameter: 419 . lg - the line graph context 420 421 Level: intermediate 422 423 .seealso: `PetscDrawLG`, `PetscDrawSPDraw()`, `PetscDrawLGSPDraw()`, `PetscDrawLGReset()` 424 @*/ 425 PetscErrorCode PetscDrawLGDraw(PetscDrawLG lg) 426 { 427 PetscReal xmin, xmax, ymin, ymax; 428 PetscMPIInt rank; 429 PetscDraw draw; 430 PetscBool isnull; 431 432 PetscFunctionBegin; 433 PetscValidHeaderSpecific(lg, PETSC_DRAWLG_CLASSID, 1); 434 PetscCall(PetscDrawIsNull(lg->win, &isnull)); 435 if (isnull) PetscFunctionReturn(0); 436 PetscCallMPI(MPI_Comm_rank(PetscObjectComm((PetscObject)lg), &rank)); 437 438 draw = lg->win; 439 PetscCall(PetscDrawCheckResizedWindow(draw)); 440 PetscCall(PetscDrawClear(draw)); 441 442 xmin = lg->xmin; 443 xmax = lg->xmax; 444 ymin = lg->ymin; 445 ymax = lg->ymax; 446 PetscCall(PetscDrawAxisSetLimits(lg->axis, xmin, xmax, ymin, ymax)); 447 PetscCall(PetscDrawAxisDraw(lg->axis)); 448 449 PetscDrawCollectiveBegin(draw); 450 if (rank == 0) { 451 int i, j, dim = lg->dim, nopts = lg->nopts, cl; 452 for (i = 0; i < dim; i++) { 453 for (j = 1; j < nopts; j++) { 454 cl = lg->colors ? lg->colors[i] : ((PETSC_DRAW_BLACK + i) % PETSC_DRAW_MAXCOLOR); 455 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)); 456 if (lg->use_markers) PetscCall(PetscDrawMarker(draw, lg->x[j * dim + i], lg->y[j * dim + i], cl)); 457 } 458 } 459 } 460 if (rank == 0 && lg->legend) { 461 PetscBool right = PETSC_FALSE; 462 int i, dim = lg->dim, cl; 463 PetscReal xl, yl, xr, yr, tw, th; 464 size_t slen, len = 0; 465 PetscCall(PetscDrawAxisGetLimits(lg->axis, &xl, &xr, &yl, &yr)); 466 PetscCall(PetscDrawStringGetSize(draw, &tw, &th)); 467 for (i = 0; i < dim; i++) { 468 PetscCall(PetscStrlen(lg->legend[i], &slen)); 469 len = PetscMax(len, slen); 470 } 471 if (right) { 472 xr = xr - 1.5 * tw; 473 xl = xr - (len + 7) * tw; 474 } else { 475 xl = xl + 1.5 * tw; 476 xr = xl + (len + 7) * tw; 477 } 478 yr = yr - 1.0 * th; 479 yl = yr - (dim + 1) * th; 480 PetscCall(PetscDrawLine(draw, xl, yl, xr, yl, PETSC_DRAW_BLACK)); 481 PetscCall(PetscDrawLine(draw, xr, yl, xr, yr, PETSC_DRAW_BLACK)); 482 PetscCall(PetscDrawLine(draw, xr, yr, xl, yr, PETSC_DRAW_BLACK)); 483 PetscCall(PetscDrawLine(draw, xl, yr, xl, yl, PETSC_DRAW_BLACK)); 484 for (i = 0; i < dim; i++) { 485 cl = lg->colors ? lg->colors[i] : (PETSC_DRAW_BLACK + i); 486 PetscCall(PetscDrawLine(draw, xl + 1 * tw, yr - (i + 1) * th, xl + 5 * tw, yr - (i + 1) * th, cl)); 487 PetscCall(PetscDrawString(draw, xl + 6 * tw, yr - (i + 1.5) * th, PETSC_DRAW_BLACK, lg->legend[i])); 488 } 489 } 490 PetscDrawCollectiveEnd(draw); 491 492 PetscCall(PetscDrawFlush(draw)); 493 PetscCall(PetscDrawPause(draw)); 494 PetscFunctionReturn(0); 495 } 496 497 /*@ 498 PetscDrawLGSave - Saves a drawn image 499 500 Collective on lg 501 502 Input Parameter: 503 . lg - The line graph context 504 505 Level: intermediate 506 507 .seealso: `PetscDrawLG`, `PetscDrawSave()`, `PetscDrawLGCreate()`, `PetscDrawLGGetDraw()`, `PetscDrawSetSave()`, `PetscDrawSave()` 508 @*/ 509 PetscErrorCode PetscDrawLGSave(PetscDrawLG lg) 510 { 511 PetscFunctionBegin; 512 PetscValidHeaderSpecific(lg, PETSC_DRAWLG_CLASSID, 1); 513 PetscCall(PetscDrawSave(lg->win)); 514 PetscFunctionReturn(0); 515 } 516 517 /*@ 518 PetscDrawLGView - Prints a line graph. 519 520 Collective on lg 521 522 Input Parameter: 523 . lg - the line graph context 524 525 Level: beginner 526 527 .seealso: `PetscDrawLG`, `PetscDrawLGCreate()` 528 @*/ 529 PetscErrorCode PetscDrawLGView(PetscDrawLG lg, PetscViewer viewer) 530 { 531 PetscReal xmin = lg->xmin, xmax = lg->xmax, ymin = lg->ymin, ymax = lg->ymax; 532 PetscInt i, j, dim = lg->dim, nopts = lg->nopts; 533 534 PetscFunctionBegin; 535 PetscValidHeaderSpecific(lg, PETSC_DRAWLG_CLASSID, 1); 536 537 if (nopts < 1) PetscFunctionReturn(0); 538 if (xmin > xmax || ymin > ymax) PetscFunctionReturn(0); 539 540 if (!viewer) PetscCall(PetscViewerASCIIGetStdout(PetscObjectComm((PetscObject)lg), &viewer)); 541 PetscCall(PetscObjectPrintClassNamePrefixType((PetscObject)lg, viewer)); 542 for (i = 0; i < dim; i++) { 543 PetscCall(PetscViewerASCIIPrintf(viewer, "Line %" PetscInt_FMT ">\n", i)); 544 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])); 545 } 546 PetscFunctionReturn(0); 547 } 548 549 /*@C 550 PetscDrawLGSetOptionsPrefix - Sets the prefix used for searching for all 551 `PetscDrawLG` options in the database. 552 553 Logically Collective on lg 554 555 Input Parameters: 556 + lg - the line graph context 557 - prefix - the prefix to prepend to all option names 558 559 Level: advanced 560 561 .seealso: `PetscDrawLG`, `PetscDrawLGSetFromOptions()`, `PetscDrawLGCreate()` 562 @*/ 563 PetscErrorCode PetscDrawLGSetOptionsPrefix(PetscDrawLG lg, const char prefix[]) 564 { 565 PetscFunctionBegin; 566 PetscValidHeaderSpecific(lg, PETSC_DRAWLG_CLASSID, 1); 567 PetscCall(PetscObjectSetOptionsPrefix((PetscObject)lg, prefix)); 568 PetscFunctionReturn(0); 569 } 570 571 /*@ 572 PetscDrawLGSetFromOptions - Sets options related to the line graph object 573 574 Collective on lg 575 576 Input Parameters: 577 . lg - the line graph context 578 579 Options Database Key: 580 . -lg_use_markers <true,false> - true means it draws a marker for each point 581 582 Level: intermediate 583 584 .seealso: `PetscDrawLG`, `PetscDrawLGDestroy()`, `PetscDrawLGCreate()` 585 @*/ 586 PetscErrorCode PetscDrawLGSetFromOptions(PetscDrawLG lg) 587 { 588 PetscBool usemarkers, set; 589 PetscDrawMarkerType markertype; 590 591 PetscFunctionBegin; 592 PetscValidHeaderSpecific(lg, PETSC_DRAWLG_CLASSID, 1); 593 594 PetscCall(PetscDrawGetMarkerType(lg->win, &markertype)); 595 PetscCall(PetscOptionsGetEnum(((PetscObject)lg)->options, ((PetscObject)lg)->prefix, "-lg_marker_type", PetscDrawMarkerTypes, (PetscEnum *)&markertype, &set)); 596 if (set) { 597 PetscCall(PetscDrawLGSetUseMarkers(lg, PETSC_TRUE)); 598 PetscCall(PetscDrawSetMarkerType(lg->win, markertype)); 599 } 600 usemarkers = lg->use_markers; 601 PetscCall(PetscOptionsGetBool(((PetscObject)lg)->options, ((PetscObject)lg)->prefix, "-lg_use_markers", &usemarkers, &set)); 602 if (set) PetscCall(PetscDrawLGSetUseMarkers(lg, usemarkers)); 603 PetscFunctionReturn(0); 604 } 605