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