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