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