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