xref: /petsc/src/sys/classes/draw/utils/lgc.c (revision 4e278199b78715991f5c71ebbd945c1489263e6c)
1 
2 #include <petscviewer.h>
3 #include <../src/sys/classes/draw/utils/lgimpl.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) {
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*CHUNCKSIZE,&lg->x,dim*CHUNCKSIZE,&lg->y);CHKERRQ(ierr);
176   ierr = PetscLogObjectMemory((PetscObject)lg,2*dim*CHUNCKSIZE*sizeof(PetscReal));CHKERRQ(ierr);
177 
178   lg->len         = dim*CHUNCKSIZE;
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 Parameter:
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 Parameter:
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 Parameter:
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*CHUNCKSIZE,&lg->x,dim*CHUNCKSIZE,&lg->y);CHKERRQ(ierr);
316   ierr    = PetscLogObjectMemory((PetscObject)lg,2*dim*CHUNCKSIZE*sizeof(PetscReal));CHKERRQ(ierr);
317   lg->len = dim*CHUNCKSIZE;
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 @*/
362 PetscErrorCode  PetscDrawLGReset(PetscDrawLG lg)
363 {
364   PetscFunctionBegin;
365   PetscValidHeaderSpecific(lg,PETSC_DRAWLG_CLASSID,1);
366   lg->xmin  = 1.e20;
367   lg->ymin  = 1.e20;
368   lg->xmax  = -1.e20;
369   lg->ymax  = -1.e20;
370   lg->loc   = 0;
371   lg->nopts = 0;
372   PetscFunctionReturn(0);
373 }
374 
375 /*@
376    PetscDrawLGDestroy - Frees all space taken up by line graph data structure.
377 
378    Collective on PetscDrawLG
379 
380    Input Parameter:
381 .  lg - the line graph context
382 
383    Level: intermediate
384 
385 .seealso:  PetscDrawLGCreate()
386 @*/
387 PetscErrorCode  PetscDrawLGDestroy(PetscDrawLG *lg)
388 {
389   PetscErrorCode ierr;
390   PetscInt       i;
391 
392   PetscFunctionBegin;
393   if (!*lg) PetscFunctionReturn(0);
394   PetscValidHeaderSpecific(*lg,PETSC_DRAWLG_CLASSID,1);
395   if (--((PetscObject)(*lg))->refct > 0) {*lg = NULL; PetscFunctionReturn(0);}
396 
397   if ((*lg)->legend) {
398     for (i=0; i<(*lg)->dim; i++) {
399       ierr = PetscFree((*lg)->legend[i]);CHKERRQ(ierr);
400     }
401     ierr = PetscFree((*lg)->legend);CHKERRQ(ierr);
402   }
403   ierr = PetscFree((*lg)->colors);CHKERRQ(ierr);
404   ierr = PetscFree2((*lg)->x,(*lg)->y);CHKERRQ(ierr);
405   ierr = PetscDrawAxisDestroy(&(*lg)->axis);CHKERRQ(ierr);
406   ierr = PetscDrawDestroy(&(*lg)->win);CHKERRQ(ierr);
407   ierr = PetscHeaderDestroy(lg);CHKERRQ(ierr);
408   PetscFunctionReturn(0);
409 }
410 /*@
411    PetscDrawLGSetUseMarkers - Causes LG to draw a marker for each data-point.
412 
413    Logically Collective on PetscDrawLG
414 
415    Input Parameters:
416 +  lg - the linegraph context
417 -  flg - should mark each data point
418 
419    Options Database:
420 .  -lg_use_markers  <true,false>
421 
422    Level: intermediate
423 
424 .seealso: PetscDrawLGCreate()
425 
426 @*/
427 PetscErrorCode  PetscDrawLGSetUseMarkers(PetscDrawLG lg,PetscBool flg)
428 {
429   PetscFunctionBegin;
430   PetscValidHeaderSpecific(lg,PETSC_DRAWLG_CLASSID,1);
431   PetscValidLogicalCollectiveBool(lg,flg,2);
432   lg->use_markers = flg;
433   PetscFunctionReturn(0);
434 }
435 
436 /*@
437    PetscDrawLGDraw - Redraws a line graph.
438 
439    Collective on PetscDrawLG
440 
441    Input Parameter:
442 .  lg - the line graph context
443 
444    Level: intermediate
445 
446 .seealso: PetscDrawSPDraw(), PetscDrawLGSPDraw(), PetscDrawLGReset()
447 
448 @*/
449 PetscErrorCode  PetscDrawLGDraw(PetscDrawLG lg)
450 {
451   PetscReal      xmin,xmax,ymin,ymax;
452   PetscErrorCode ierr;
453   PetscMPIInt    rank;
454   PetscDraw      draw;
455   PetscBool      isnull;
456 
457   PetscFunctionBegin;
458   PetscValidHeaderSpecific(lg,PETSC_DRAWLG_CLASSID,1);
459   ierr = PetscDrawIsNull(lg->win,&isnull);CHKERRQ(ierr);
460   if (isnull) PetscFunctionReturn(0);
461   ierr = MPI_Comm_rank(PetscObjectComm((PetscObject)lg),&rank);CHKERRMPI(ierr);
462 
463   draw = lg->win;
464   ierr = PetscDrawCheckResizedWindow(draw);CHKERRQ(ierr);
465   ierr = PetscDrawClear(draw);CHKERRQ(ierr);
466 
467   xmin = lg->xmin; xmax = lg->xmax; ymin = lg->ymin; ymax = lg->ymax;
468   ierr = PetscDrawAxisSetLimits(lg->axis,xmin,xmax,ymin,ymax);CHKERRQ(ierr);
469   ierr = PetscDrawAxisDraw(lg->axis);CHKERRQ(ierr);
470 
471   ierr = PetscDrawCollectiveBegin(draw);CHKERRQ(ierr);
472   if (!rank) {
473     int i,j,dim=lg->dim,nopts=lg->nopts,cl;
474     for (i=0; i<dim; i++) {
475       for (j=1; j<nopts; j++) {
476         cl   = lg->colors ? lg->colors[i] : ((PETSC_DRAW_BLACK + i) % PETSC_DRAW_MAXCOLOR);
477         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);
478         if (lg->use_markers) {ierr = PetscDrawMarker(draw,lg->x[j*dim+i],lg->y[j*dim+i],cl);CHKERRQ(ierr);}
479       }
480     }
481   }
482   if (!rank && lg->legend) {
483     int       i,dim=lg->dim,cl;
484     PetscReal xl,yl,xr,yr,tw,th;
485     size_t    slen,len=0;
486     ierr = PetscDrawAxisGetLimits(lg->axis,&xl,&xr,&yl,&yr);CHKERRQ(ierr);
487     ierr = PetscDrawStringGetSize(draw,&tw,&th);CHKERRQ(ierr);
488     for (i=0; i<dim; i++) {
489       ierr = PetscStrlen(lg->legend[i],&slen);CHKERRQ(ierr);
490       len = PetscMax(len,slen);
491     }
492     xr = xr - 1.5*tw; xl = xr - (len + 7)*tw;
493     yr = yr - 1.0*th; yl = yr - (dim + 1)*th;
494     ierr = PetscDrawLine(draw,xl,yl,xr,yl,PETSC_DRAW_BLACK);CHKERRQ(ierr);
495     ierr = PetscDrawLine(draw,xr,yl,xr,yr,PETSC_DRAW_BLACK);CHKERRQ(ierr);
496     ierr = PetscDrawLine(draw,xr,yr,xl,yr,PETSC_DRAW_BLACK);CHKERRQ(ierr);
497     ierr = PetscDrawLine(draw,xl,yr,xl,yl,PETSC_DRAW_BLACK);CHKERRQ(ierr);
498     for  (i=0; i<dim; i++) {
499       cl   = lg->colors ? lg->colors[i] : (PETSC_DRAW_BLACK + i);
500       ierr = PetscDrawLine(draw,xl + 1*tw,yr - (i + 1)*th,xl + 5*tw,yr - (i + 1)*th,cl);CHKERRQ(ierr);
501       ierr = PetscDrawString(draw,xl + 6*tw,yr - (i + 1.5)*th,PETSC_DRAW_BLACK,lg->legend[i]);CHKERRQ(ierr);
502     }
503   }
504   ierr = PetscDrawCollectiveEnd(draw);CHKERRQ(ierr);
505 
506   ierr = PetscDrawFlush(draw);CHKERRQ(ierr);
507   ierr = PetscDrawPause(draw);CHKERRQ(ierr);
508   PetscFunctionReturn(0);
509 }
510 
511 /*@
512   PetscDrawLGSave - Saves a drawn image
513 
514   Collective on PetscDrawLG
515 
516   Input Parameter:
517 . lg - The line graph context
518 
519   Level: intermediate
520 
521 .seealso:  PetscDrawLGCreate(), PetscDrawLGGetDraw(), PetscDrawSetSave(), PetscDrawSave()
522 @*/
523 PetscErrorCode  PetscDrawLGSave(PetscDrawLG lg)
524 {
525   PetscErrorCode ierr;
526 
527   PetscFunctionBegin;
528   PetscValidHeaderSpecific(lg,PETSC_DRAWLG_CLASSID,1);
529   ierr = PetscDrawSave(lg->win);CHKERRQ(ierr);
530   PetscFunctionReturn(0);
531 }
532 
533 /*@
534   PetscDrawLGView - Prints a line graph.
535 
536   Collective on PetscDrawLG
537 
538   Input Parameter:
539 . lg - the line graph context
540 
541   Level: beginner
542 
543 .seealso: PetscDrawLGCreate()
544 
545 @*/
546 PetscErrorCode  PetscDrawLGView(PetscDrawLG lg,PetscViewer viewer)
547 {
548   PetscReal      xmin=lg->xmin, xmax=lg->xmax, ymin=lg->ymin, ymax=lg->ymax;
549   PetscInt       i, j, dim = lg->dim, nopts = lg->nopts;
550   PetscErrorCode ierr;
551 
552   PetscFunctionBegin;
553   PetscValidHeaderSpecific(lg,PETSC_DRAWLG_CLASSID,1);
554 
555   if (nopts < 1)                  PetscFunctionReturn(0);
556   if (xmin > xmax || ymin > ymax) PetscFunctionReturn(0);
557 
558   if (!viewer){
559     ierr = PetscViewerASCIIGetStdout(PetscObjectComm((PetscObject)lg),&viewer);CHKERRQ(ierr);
560   }
561   ierr = PetscObjectPrintClassNamePrefixType((PetscObject)lg,viewer);CHKERRQ(ierr);
562   for (i = 0; i < dim; i++) {
563     ierr = PetscViewerASCIIPrintf(viewer, "Line %D>\n", i);CHKERRQ(ierr);
564     for (j = 0; j < nopts; j++) {
565       ierr = PetscViewerASCIIPrintf(viewer, "  X: %g Y: %g\n", (double)lg->x[j*dim+i], (double)lg->y[j*dim+i]);CHKERRQ(ierr);
566     }
567   }
568   PetscFunctionReturn(0);
569 }
570 
571 /*@C
572    PetscDrawLGSetOptionsPrefix - Sets the prefix used for searching for all
573    PetscDrawLG options in the database.
574 
575    Logically Collective on PetscDrawLG
576 
577    Input Parameter:
578 +  lg - the line graph context
579 -  prefix - the prefix to prepend to all option names
580 
581    Level: advanced
582 
583 .seealso: PetscDrawLGSetFromOptions(), PetscDrawLGCreate()
584 @*/
585 PetscErrorCode  PetscDrawLGSetOptionsPrefix(PetscDrawLG lg,const char prefix[])
586 {
587   PetscErrorCode ierr;
588 
589   PetscFunctionBegin;
590   PetscValidHeaderSpecific(lg,PETSC_DRAWLG_CLASSID,1);
591   ierr = PetscObjectSetOptionsPrefix((PetscObject)lg,prefix);CHKERRQ(ierr);
592   PetscFunctionReturn(0);
593 }
594 
595 /*@
596     PetscDrawLGSetFromOptions - Sets options related to the PetscDrawLG
597 
598     Collective on PetscDrawLG
599 
600     Options Database:
601 
602     Level: intermediate
603 
604 .seealso:  PetscDrawLGDestroy(), PetscDrawLGCreate()
605 @*/
606 PetscErrorCode  PetscDrawLGSetFromOptions(PetscDrawLG lg)
607 {
608   PetscErrorCode      ierr;
609   PetscBool           usemarkers,set;
610   PetscDrawMarkerType markertype;
611 
612   PetscFunctionBegin;
613   PetscValidHeaderSpecific(lg,PETSC_DRAWLG_CLASSID,1);
614 
615   ierr = PetscDrawGetMarkerType(lg->win,&markertype);CHKERRQ(ierr);
616   ierr = PetscOptionsGetEnum(((PetscObject)lg)->options,((PetscObject)lg)->prefix,"-lg_marker_type",PetscDrawMarkerTypes,(PetscEnum*)&markertype,&set);CHKERRQ(ierr);
617   if (set) {
618     ierr = PetscDrawLGSetUseMarkers(lg,PETSC_TRUE);CHKERRQ(ierr);
619     ierr = PetscDrawSetMarkerType(lg->win,markertype);CHKERRQ(ierr);
620   }
621   usemarkers = lg->use_markers;
622   ierr = PetscOptionsGetBool(((PetscObject)lg)->options,((PetscObject)lg)->prefix,"-lg_use_markers",&usemarkers,&set);CHKERRQ(ierr);
623   if (set) {ierr = PetscDrawLGSetUseMarkers(lg,usemarkers);CHKERRQ(ierr);}
624   PetscFunctionReturn(0);
625 }
626