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