Actual source code: lgc.c

      1: #include <petscviewer.h>
      2: #include <petsc/private/drawimpl.h>
      3: PetscClassId PETSC_DRAWLG_CLASSID = 0;

      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.

     11:   Not Collective, if lg is parallel then axis is parallel

     13:   Input Parameter:
     14: . lg - the line graph context

     16:   Output Parameter:
     17: . axis - the axis context

     19:   Level: advanced

     21: .seealso: `PetscDrawLGCreate()`, `PetscDrawAxis`, `PetscDrawLG`
     22: @*/
     23: PetscErrorCode PetscDrawLGGetAxis(PetscDrawLG lg, PetscDrawAxis *axis)
     24: {
     25:   PetscFunctionBegin;
     27:   PetscAssertPointer(axis, 2);
     28:   *axis = lg->axis;
     29:   PetscFunctionReturn(PETSC_SUCCESS);
     30: }

     32: /*@
     33:   PetscDrawLGGetDraw - Gets the draw context associated with a line graph.

     35:   Not Collective, if lg is parallel then draw is parallel

     37:   Input Parameter:
     38: . lg - the line graph context

     40:   Output Parameter:
     41: . draw - the draw context

     43:   Level: intermediate

     45: .seealso: `PetscDrawLGCreate()`, `PetscDraw`, `PetscDrawLG`
     46: @*/
     47: PetscErrorCode PetscDrawLGGetDraw(PetscDrawLG lg, PetscDraw *draw)
     48: {
     49:   PetscFunctionBegin;
     51:   PetscAssertPointer(draw, 2);
     52:   *draw = lg->win;
     53:   PetscFunctionReturn(PETSC_SUCCESS);
     54: }

     56: /*@
     57:   PetscDrawLGSPDraw - Redraws a line graph and a scatter plot on the same `PetscDraw` they must share

     59:   Collective

     61:   Input Parameters:
     62: + lg   - the line graph context
     63: - spin - the scatter plot

     65:   Level: intermediate

     67:   Developer Notes:
     68:   This code cheats and uses the fact that the `PetscDrawLG` and `PetscDrawSP` structs are the same

     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;

     80:   PetscFunctionBegin;
     83:   PetscCall(PetscDrawIsNull(lg->win, &isnull));
     84:   if (isnull) PetscFunctionReturn(PETSC_SUCCESS);
     85:   PetscCallMPI(MPI_Comm_rank(PetscObjectComm((PetscObject)lg), &rank));

     87:   draw = lg->win;
     88:   PetscCall(PetscDrawCheckResizedWindow(draw));
     89:   PetscCall(PetscDrawClear(draw));

     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));

     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);

    117:   PetscCall(PetscDrawFlush(draw));
    118:   PetscCall(PetscDrawPause(draw));
    119:   PetscFunctionReturn(PETSC_SUCCESS);
    120: }

    122: /*@
    123:   PetscDrawLGCreate - Creates a line graph data structure.

    125:   Collective

    127:   Input Parameters:
    128: + draw - the window where the graph will be made.
    129: - dim  - the number of curves which will be drawn

    131:   Output Parameter:
    132: . outlg - the line graph context

    134:   Level: intermediate

    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.

    140:   All MPI ranks in the communicator must call `PetscDrawLGDraw()` to display the updated graph.

    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;

    150:   PetscFunctionBegin;
    153:   PetscAssertPointer(outlg, 3);

    155:   PetscCall(PetscHeaderCreate(lg, PETSC_DRAWLG_CLASSID, "DrawLG", "Line Graph", "Draw", PetscObjectComm((PetscObject)draw), PetscDrawLGDestroy, NULL));
    156:   PetscCall(PetscDrawLGSetOptionsPrefix(lg, ((PetscObject)draw)->prefix));

    158:   PetscCall(PetscObjectReference((PetscObject)draw));
    159:   lg->win = draw;

    161:   lg->view    = NULL;
    162:   lg->destroy = NULL;
    163:   lg->nopts   = 0;
    164:   lg->dim     = (int)dim;
    165:   lg->xmin    = 1.e20;
    166:   lg->ymin    = 1.e20;
    167:   lg->xmax    = -1.e20;
    168:   lg->ymax    = -1.e20;

    170:   PetscCall(PetscMalloc2(dim * PETSC_DRAW_LG_CHUNK_SIZE, &lg->x, dim * PETSC_DRAW_LG_CHUNK_SIZE, &lg->y));

    172:   lg->len         = (int)(dim * PETSC_DRAW_LG_CHUNK_SIZE);
    173:   lg->loc         = 0;
    174:   lg->use_markers = PETSC_FALSE;

    176:   PetscCall(PetscDrawAxisCreate(draw, &lg->axis));

    178:   *outlg = lg;
    179:   PetscFunctionReturn(PETSC_SUCCESS);
    180: }

    182: /*@
    183:   PetscDrawLGSetColors - Sets the color of each line graph drawn

    185:   Logically Collective

    187:   Input Parameters:
    188: + lg     - the line graph context.
    189: - colors - the colors

    191:   Level: intermediate

    193: .seealso: `PetscDrawLG`, `PetscDrawLGCreate()`
    194: @*/
    195: PetscErrorCode PetscDrawLGSetColors(PetscDrawLG lg, const int colors[])
    196: {
    197:   PetscFunctionBegin;
    199:   if (lg->dim) PetscAssertPointer(colors, 2);

    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: }

    207: /*@C
    208:   PetscDrawLGSetLegend - sets the names of each curve plotted

    210:   Logically Collective

    212:   Input Parameters:
    213: + lg    - the line graph context.
    214: - names - the names for each curve

    216:   Level: intermediate

    218:   Note:
    219:   Call `PetscDrawLGGetAxis()` and then change properties of the `PetscDrawAxis` for detailed control of the plot

    221: .seealso: `PetscDrawLGGetAxis()`, `PetscDrawAxis`, `PetscDrawAxisSetColors()`, `PetscDrawAxisSetLabels()`, `PetscDrawAxisSetHoldLimits()`
    222: @*/
    223: PetscErrorCode PetscDrawLGSetLegend(PetscDrawLG lg, const char *const names[])
    224: {
    225:   PetscInt i;

    227:   PetscFunctionBegin;
    229:   if (names) PetscAssertPointer(names, 2);

    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: }

    242: /*@
    243:   PetscDrawLGGetDimension - Get the number of curves that are to be drawn.

    245:   Not Collective

    247:   Input Parameter:
    248: . lg - the line graph context.

    250:   Output Parameter:
    251: . dim - the number of curves.

    253:   Level: intermediate

    255: .seealso: `PetscDrawLGC`, `PetscDrawLGCreate()`, `PetscDrawLGSetDimension()`
    256: @*/
    257: PetscErrorCode PetscDrawLGGetDimension(PetscDrawLG lg, PetscInt *dim)
    258: {
    259:   PetscFunctionBegin;
    261:   PetscAssertPointer(dim, 2);
    262:   *dim = lg->dim;
    263:   PetscFunctionReturn(PETSC_SUCCESS);
    264: }

    266: /*@
    267:   PetscDrawLGSetDimension - Change the number of curves that are to be drawn.

    269:   Logically Collective

    271:   Input Parameters:
    272: + lg  - the line graph context.
    273: - dim - the number of curves.

    275:   Level: intermediate

    277: .seealso: `PetscDrawLGCreate()`, `PetscDrawLGGetDimension()`
    278: @*/
    279: PetscErrorCode PetscDrawLGSetDimension(PetscDrawLG lg, PetscInt dim)
    280: {
    281:   PetscInt i;

    283:   PetscFunctionBegin;
    286:   if (lg->dim == dim) PetscFunctionReturn(PETSC_SUCCESS);

    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 = (int)dim;
    295:   PetscCall(PetscMalloc2(dim * PETSC_DRAW_LG_CHUNK_SIZE, &lg->x, dim * PETSC_DRAW_LG_CHUNK_SIZE, &lg->y));
    296:   lg->len = (int)(dim * PETSC_DRAW_LG_CHUNK_SIZE);
    297:   PetscFunctionReturn(PETSC_SUCCESS);
    298: }

    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.

    305:   Logically Collective

    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

    314:   Level: intermediate

    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;

    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: }

    330: /*@
    331:   PetscDrawLGReset - Clears line graph to allow for reuse with new data.

    333:   Logically Collective

    335:   Input Parameter:
    336: . lg - the line graph context.

    338:   Level: intermediate

    340: .seealso: `PetscDrawLG`, `PetscDrawLGCreate()`
    341: @*/
    342: PetscErrorCode PetscDrawLGReset(PetscDrawLG lg)
    343: {
    344:   PetscFunctionBegin;
    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: }

    355: /*@
    356:   PetscDrawLGDestroy - Frees all space taken up by line graph data structure.

    358:   Collective

    360:   Input Parameter:
    361: . lg - the line graph context

    363:   Level: intermediate

    365: .seealso: `PetscDrawLG`, `PetscDrawLGCreate()`
    366: @*/
    367: PetscErrorCode PetscDrawLGDestroy(PetscDrawLG *lg)
    368: {
    369:   PetscInt i;

    371:   PetscFunctionBegin;
    372:   if (!*lg) PetscFunctionReturn(PETSC_SUCCESS);
    374:   if (--((PetscObject)*lg)->refct > 0) {
    375:     *lg = NULL;
    376:     PetscFunctionReturn(PETSC_SUCCESS);
    377:   }

    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.

    393:   Logically Collective

    395:   Input Parameters:
    396: + lg  - the linegraph context
    397: - flg - should mark each data point

    399:   Options Database Key:
    400: . -lg_use_markers  <true,false> - true means it draws a marker for each point

    402:   Level: intermediate

    404: .seealso: `PetscDrawLG`, `PetscDrawLGCreate()`
    405: @*/
    406: PetscErrorCode PetscDrawLGSetUseMarkers(PetscDrawLG lg, PetscBool flg)
    407: {
    408:   PetscFunctionBegin;
    411:   lg->use_markers = flg;
    412:   PetscFunctionReturn(PETSC_SUCCESS);
    413: }

    415: /*@
    416:   PetscDrawLGDraw - Redraws a line graph.

    418:   Collective

    420:   Input Parameter:
    421: . lg - the line graph context

    423:   Level: intermediate

    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;

    434:   PetscFunctionBegin;
    436:   PetscCall(PetscDrawIsNull(lg->win, &isnull));
    437:   if (isnull) PetscFunctionReturn(PETSC_SUCCESS);
    438:   PetscCallMPI(MPI_Comm_rank(PetscObjectComm((PetscObject)lg), &rank));

    440:   draw = lg->win;
    441:   PetscCall(PetscDrawCheckResizedWindow(draw));
    442:   PetscCall(PetscDrawClear(draw));

    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));

    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;

    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 - ((PetscReal)len + 7) * tw;
    477:     } else {
    478:       xl = xl + 1.5 * tw;
    479:       xr = xl + ((PetscReal)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);

    495:   PetscCall(PetscDrawFlush(draw));
    496:   PetscCall(PetscDrawPause(draw));
    497:   PetscFunctionReturn(PETSC_SUCCESS);
    498: }

    500: /*@
    501:   PetscDrawLGSave - Saves a drawn image

    503:   Collective

    505:   Input Parameter:
    506: . lg - The line graph context

    508:   Level: intermediate

    510: .seealso: `PetscDrawLG`, `PetscDrawSave()`, `PetscDrawLGCreate()`, `PetscDrawLGGetDraw()`, `PetscDrawSetSave()`
    511: @*/
    512: PetscErrorCode PetscDrawLGSave(PetscDrawLG lg)
    513: {
    514:   PetscFunctionBegin;
    516:   PetscCall(PetscDrawSave(lg->win));
    517:   PetscFunctionReturn(PETSC_SUCCESS);
    518: }

    520: /*@
    521:   PetscDrawLGView - Prints a line graph.

    523:   Collective

    525:   Input Parameters:
    526: + lg     - the line graph context
    527: - viewer - the viewer to view it with

    529:   Level: beginner

    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;

    538:   PetscFunctionBegin;

    541:   if (nopts < 1) PetscFunctionReturn(PETSC_SUCCESS);
    542:   if (xmin > xmax || ymin > ymax) PetscFunctionReturn(PETSC_SUCCESS);

    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: }

    553: /*@
    554:   PetscDrawLGSetOptionsPrefix - Sets the prefix used for searching for all
    555:   `PetscDrawLG` options in the database.

    557:   Logically Collective

    559:   Input Parameters:
    560: + lg     - the line graph context
    561: - prefix - the prefix to prepend to all option names

    563:   Level: advanced

    565: .seealso: `PetscDrawLG`, `PetscDrawLGSetFromOptions()`, `PetscDrawLGCreate()`
    566: @*/
    567: PetscErrorCode PetscDrawLGSetOptionsPrefix(PetscDrawLG lg, const char prefix[])
    568: {
    569:   PetscFunctionBegin;
    571:   PetscCall(PetscObjectSetOptionsPrefix((PetscObject)lg, prefix));
    572:   PetscFunctionReturn(PETSC_SUCCESS);
    573: }

    575: /*@
    576:   PetscDrawLGSetFromOptions - Sets options related to the line graph object

    578:   Collective

    580:   Input Parameters:
    581: . lg - the line graph context

    583:   Options Database Key:
    584: . -lg_use_markers  <true,false> - true means it draws a marker for each point

    586:   Level: intermediate

    588: .seealso: `PetscDrawLG`, `PetscDrawLGDestroy()`, `PetscDrawLGCreate()`
    589: @*/
    590: PetscErrorCode PetscDrawLGSetFromOptions(PetscDrawLG lg)
    591: {
    592:   PetscBool           usemarkers, set;
    593:   PetscDrawMarkerType markertype;

    595:   PetscFunctionBegin;

    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: }