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