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