xref: /petsc/src/sys/classes/draw/utils/lgc.c (revision 3e1910f1ab6113d8365e15c6b8c907ccce7ce4ea)
1 
2 #include <../src/sys/classes/draw/utils/lgimpl.h>  /*I   "petscdraw.h"  I*/
3 #include <petscviewer.h>
4 PetscClassId PETSC_DRAWLG_CLASSID = 0;
5 
6 #undef __FUNCT__
7 #define __FUNCT__ "PetscDrawLGGetAxis"
8 /*@
9    PetscDrawLGGetAxis - Gets the axis context associated with a line graph.
10    This is useful if one wants to change some axis property, such as
11    labels, color, etc. The axis context should not be destroyed by the
12    application code.
13 
14    Not Collective, if PetscDrawLG is parallel then PetscDrawAxis is parallel
15 
16    Input Parameter:
17 .  lg - the line graph context
18 
19    Output Parameter:
20 .  axis - the axis context
21 
22    Level: advanced
23 
24 @*/
25 PetscErrorCode  PetscDrawLGGetAxis(PetscDrawLG lg,PetscDrawAxis *axis)
26 {
27   PetscFunctionBegin;
28   if (lg && ((PetscObject)lg)->classid == PETSC_DRAW_CLASSID) {
29     *axis = 0;
30     PetscFunctionReturn(0);
31   }
32   PetscValidHeaderSpecific(lg,PETSC_DRAWLG_CLASSID,1);
33   PetscValidPointer(axis,2);
34   *axis = lg->axis;
35   PetscFunctionReturn(0);
36 }
37 
38 #undef __FUNCT__
39 #define __FUNCT__ "PetscDrawLGGetDraw"
40 /*@
41    PetscDrawLGGetDraw - Gets the draw context associated with a line graph.
42 
43    Not Collective, if PetscDrawLG is parallel then PetscDraw is parallel
44 
45    Input Parameter:
46 .  lg - the line graph context
47 
48    Output Parameter:
49 .  draw - the draw context
50 
51    Level: intermediate
52 
53 @*/
54 PetscErrorCode  PetscDrawLGGetDraw(PetscDrawLG lg,PetscDraw *draw)
55 {
56   PetscFunctionBegin;
57   PetscValidHeader(lg,1);
58   PetscValidPointer(draw,2);
59   if (((PetscObject)lg)->classid == PETSC_DRAW_CLASSID) *draw = (PetscDraw)lg;
60   else {
61     PetscValidHeaderSpecific(lg,PETSC_DRAWLG_CLASSID,1);
62     *draw = lg->win;
63   }
64   PetscFunctionReturn(0);
65 }
66 
67 
68 #undef __FUNCT__
69 #define __FUNCT__ "PetscDrawLGSPDraw"
70 /*@
71    PetscDrawLGSPDraw - Redraws a line graph.
72 
73    Not Collective,but ignored by all processors except processor 0 in PetscDrawLG
74 
75    Input Parameter:
76 .  lg - the line graph context
77 
78    Level: intermediate
79 
80 .seealso: PetscDrawLGDraw(), PetscDrawSPDraw()
81 
82    Developer Notes: This code cheats and uses the fact that the LG and SP structs are the same
83 
84 @*/
85 PetscErrorCode  PetscDrawLGSPDraw(PetscDrawLG lg,PetscDrawSP spin)
86 {
87   PetscDrawLG    sp = (PetscDrawLG)spin;
88   PetscReal      xmin,xmax,ymin,ymax;
89   PetscErrorCode ierr;
90   int            i,j,dim,nopts,rank;
91   PetscDraw      draw = lg->win;
92 
93   PetscFunctionBegin;
94   if (lg && ((PetscObject)lg)->classid == PETSC_DRAW_CLASSID) PetscFunctionReturn(0);
95   PetscValidHeaderSpecific(lg,PETSC_DRAWLG_CLASSID,1);
96   PetscValidHeaderSpecific(sp,PETSC_DRAWSP_CLASSID,2);
97 
98   xmin = PetscMin(lg->xmin,sp->xmin);
99   ymin = PetscMin(lg->ymin,sp->ymin);
100   xmax = PetscMax(lg->xmax,sp->xmax);
101   ymax = PetscMax(lg->ymax,sp->ymax);
102 
103   ierr = PetscDrawClear(draw);CHKERRQ(ierr);
104   ierr = PetscDrawAxisSetLimits(lg->axis,xmin,xmax,ymin,ymax);CHKERRQ(ierr);
105   ierr = PetscDrawAxisDraw(lg->axis);CHKERRQ(ierr);
106 
107   ierr = MPI_Comm_rank(PetscObjectComm((PetscObject)lg),&rank);CHKERRQ(ierr);
108   if (!rank) {
109 
110     dim   = lg->dim;
111     nopts = lg->nopts;
112     for (i=0; i<dim; i++) {
113       for (j=1; j<nopts; j++) {
114         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);
115         if (lg->use_dots) {
116           ierr = PetscDrawString(draw,lg->x[j*dim+i],lg->y[j*dim+i],PETSC_DRAW_RED,"x");CHKERRQ(ierr);
117         }
118       }
119     }
120 
121     dim   = sp->dim;
122     nopts = sp->nopts;
123     for (i=0; i<dim; i++) {
124       for (j=0; j<nopts; j++) {
125         ierr = PetscDrawString(draw,sp->x[j*dim+i],sp->y[j*dim+i],PETSC_DRAW_RED,"x");CHKERRQ(ierr);
126       }
127     }
128   }
129   ierr = PetscDrawFlush(lg->win);CHKERRQ(ierr);
130   ierr = PetscDrawPause(lg->win);CHKERRQ(ierr);
131   PetscFunctionReturn(0);
132 }
133 
134 
135 #undef __FUNCT__
136 #define __FUNCT__ "PetscDrawLGCreate"
137 /*@
138     PetscDrawLGCreate - Creates a line graph data structure.
139 
140     Collective over PetscDraw
141 
142     Input Parameters:
143 +   draw - the window where the graph will be made.
144 -   dim - the number of curves which will be drawn
145 
146     Output Parameters:
147 .   outctx - the line graph context
148 
149     Level: intermediate
150 
151     Concepts: line graph^creating
152 
153 .seealso:  PetscDrawLGDestroy()
154 @*/
155 PetscErrorCode  PetscDrawLGCreate(PetscDraw draw,PetscInt dim,PetscDrawLG *outctx)
156 {
157   PetscErrorCode ierr;
158   PetscBool      isnull;
159   PetscObject    obj = (PetscObject)draw;
160   PetscDrawLG    lg;
161 
162   PetscFunctionBegin;
163   PetscValidHeaderSpecific(draw,PETSC_DRAW_CLASSID,1);
164   PetscValidPointer(outctx,2);
165   ierr = PetscObjectTypeCompare(obj,PETSC_DRAW_NULL,&isnull);CHKERRQ(ierr);
166   if (isnull) {
167     ierr = PetscDrawOpenNull(PetscObjectComm((PetscObject)obj),(PetscDraw*)outctx);CHKERRQ(ierr);
168     PetscFunctionReturn(0);
169   }
170   ierr = PetscHeaderCreate(lg,_p_PetscDrawLG,int,PETSC_DRAWLG_CLASSID,"PetscDrawLG","Line graph","Draw",PetscObjectComm((PetscObject)obj),PetscDrawLGDestroy,0);CHKERRQ(ierr);
171 
172   lg->view    = 0;
173   lg->destroy = 0;
174   lg->nopts   = 0;
175   lg->win     = draw;
176   lg->dim     = dim;
177   lg->xmin    = 1.e20;
178   lg->ymin    = 1.e20;
179   lg->xmax    = -1.e20;
180   lg->ymax    = -1.e20;
181 
182   ierr = PetscMalloc2(dim*CHUNCKSIZE,PetscReal,&lg->x,dim*CHUNCKSIZE,PetscReal,&lg->y);CHKERRQ(ierr);
183   ierr = PetscLogObjectMemory(lg,2*dim*CHUNCKSIZE*sizeof(PetscReal));CHKERRQ(ierr);
184 
185   lg->len     = dim*CHUNCKSIZE;
186   lg->loc     = 0;
187   lg->use_dots= PETSC_FALSE;
188 
189   ierr = PetscDrawAxisCreate(draw,&lg->axis);CHKERRQ(ierr);
190   ierr = PetscLogObjectParent(lg,lg->axis);CHKERRQ(ierr);
191 
192   *outctx = lg;
193   PetscFunctionReturn(0);
194 }
195 
196 #undef __FUNCT__
197 #define __FUNCT__ "PetscDrawLGSetColors"
198 /*@
199    PetscDrawLGSetColors - Sets the color of each line graph drawn
200 
201    Logically Collective over PetscDrawLG
202 
203    Input Parameter:
204 +  lg - the line graph context.
205 -  colors - the colors
206 
207    Level: intermediate
208 
209    Concepts: line graph^setting number of lines
210 
211 @*/
212 PetscErrorCode  PetscDrawLGSetColors(PetscDrawLG lg,const int *colors)
213 {
214   PetscErrorCode ierr;
215 
216   PetscFunctionBegin;
217   if (lg && ((PetscObject)lg)->classid == PETSC_DRAW_CLASSID) PetscFunctionReturn(0);
218   PetscValidHeaderSpecific(lg,PETSC_DRAWLG_CLASSID,1);
219   ierr = PetscFree(lg->colors);CHKERRQ(ierr);
220   ierr = PetscMalloc(lg->dim*sizeof(int),&lg->colors);CHKERRQ(ierr);
221   ierr = PetscMemcpy(lg->colors,colors,lg->dim*sizeof(int));CHKERRQ(ierr);
222   PetscFunctionReturn(0);
223 }
224 
225 #undef __FUNCT__
226 #undef __FUNCT__
227 #define __FUNCT__ "PetscDrawLGSetLegend"
228 /*@C
229    PetscDrawLGSetLegend - sets the names of each curve plotted
230 
231    Logically Collective over PetscDrawLG
232 
233    Input Parameter:
234 +  lg - the line graph context.
235 -  names - the names for each curve
236 
237    Level: intermediate
238 
239    Concepts: line graph^setting number of lines
240 
241 @*/
242 PetscErrorCode  PetscDrawLGSetLegend(PetscDrawLG lg,const char *const *names)
243 {
244   PetscErrorCode ierr;
245   PetscInt       i;
246 
247   PetscFunctionBegin;
248   if (lg && ((PetscObject)lg)->classid == PETSC_DRAW_CLASSID) PetscFunctionReturn(0);
249   PetscValidHeaderSpecific(lg,PETSC_DRAWLG_CLASSID,1);
250 
251   if (lg->legend) {
252     for (i=0; i<lg->dim; i++) {
253       ierr = PetscFree(lg->legend[i]);CHKERRQ(ierr);
254     }
255     ierr = PetscFree(lg->legend);CHKERRQ(ierr);
256   }
257   if (names) {
258     ierr = PetscMalloc(lg->dim*sizeof(char**),&lg->legend);CHKERRQ(ierr);
259     for (i=0; i<lg->dim; i++) {
260       ierr = PetscStrallocpy(names[i],&lg->legend[i]);CHKERRQ(ierr);
261     }
262   }
263   PetscFunctionReturn(0);
264 }
265 
266 #undef __FUNCT__
267 #define __FUNCT__ "PetscDrawLGGetDimension"
268 /*@
269    PetscDrawLGGetDimension - Change the number of lines that are to be drawn.
270 
271    Logically Collective over PetscDrawLG
272 
273    Input Parameter:
274 .  lg - the line graph context.
275 
276    Output Parameter:
277 .  dim - the number of curves.
278 
279    Level: intermediate
280 
281    Concepts: line graph^setting number of lines
282 
283 @*/
284 PetscErrorCode  PetscDrawLGGetDimension(PetscDrawLG lg,PetscInt *dim)
285 {
286   PetscFunctionBegin;
287   if (lg && ((PetscObject)lg)->classid == PETSC_DRAW_CLASSID) PetscFunctionReturn(0);
288   PetscValidHeaderSpecific(lg,PETSC_DRAWLG_CLASSID,1);
289   *dim = lg->dim;
290   PetscFunctionReturn(0);
291 }
292 
293 #undef __FUNCT__
294 #define __FUNCT__ "PetscDrawLGSetDimension"
295 /*@
296    PetscDrawLGSetDimension - Change the number of lines that are to be drawn.
297 
298    Logically Collective over PetscDrawLG
299 
300    Input Parameter:
301 +  lg - the line graph context.
302 -  dim - the number of curves.
303 
304    Level: intermediate
305 
306    Concepts: line graph^setting number of lines
307 
308 @*/
309 PetscErrorCode  PetscDrawLGSetDimension(PetscDrawLG lg,PetscInt dim)
310 {
311   PetscErrorCode ierr;
312   PetscInt       i;
313 
314   PetscFunctionBegin;
315   if (lg && ((PetscObject)lg)->classid == PETSC_DRAW_CLASSID) PetscFunctionReturn(0);
316   PetscValidHeaderSpecific(lg,PETSC_DRAWLG_CLASSID,1);
317   PetscValidLogicalCollectiveInt(lg,dim,2);
318   if (lg->dim == dim) PetscFunctionReturn(0);
319 
320   ierr = PetscFree2(lg->x,lg->y);CHKERRQ(ierr);
321   if (lg->legend) {
322     for (i=0; i<lg->dim; i++) {
323       ierr = PetscFree(lg->legend[i]);CHKERRQ(ierr);
324     }
325     ierr = PetscFree(lg->legend);CHKERRQ(ierr);
326   }
327   ierr    = PetscFree(lg->colors);CHKERRQ(ierr);
328   lg->dim = dim;
329   ierr    = PetscMalloc2(dim*CHUNCKSIZE,PetscReal,&lg->x,dim*CHUNCKSIZE,PetscReal,&lg->y);CHKERRQ(ierr);
330   ierr    = PetscLogObjectMemory(lg,2*dim*CHUNCKSIZE*sizeof(PetscReal));CHKERRQ(ierr);
331   lg->len = dim*CHUNCKSIZE;
332   PetscFunctionReturn(0);
333 }
334 
335 #undef __FUNCT__
336 #define __FUNCT__ "PetscDrawLGReset"
337 /*@
338    PetscDrawLGReset - Clears line graph to allow for reuse with new data.
339 
340    Logically Collective over PetscDrawLG
341 
342    Input Parameter:
343 .  lg - the line graph context.
344 
345    Level: intermediate
346 
347    Concepts: line graph^restarting
348 
349 @*/
350 PetscErrorCode  PetscDrawLGReset(PetscDrawLG lg)
351 {
352   PetscFunctionBegin;
353   if (lg && ((PetscObject)lg)->classid == PETSC_DRAW_CLASSID) PetscFunctionReturn(0);
354   PetscValidHeaderSpecific(lg,PETSC_DRAWLG_CLASSID,1);
355   lg->xmin  = 1.e20;
356   lg->ymin  = 1.e20;
357   lg->xmax  = -1.e20;
358   lg->ymax  = -1.e20;
359   lg->loc   = 0;
360   lg->nopts = 0;
361   PetscFunctionReturn(0);
362 }
363 
364 #undef __FUNCT__
365 #define __FUNCT__ "PetscDrawLGDestroy"
366 /*@
367    PetscDrawLGDestroy - Frees all space taken up by line graph data structure.
368 
369    Collective over PetscDrawLG
370 
371    Input Parameter:
372 .  lg - the line graph context
373 
374    Level: intermediate
375 
376 .seealso:  PetscDrawLGCreate()
377 @*/
378 PetscErrorCode  PetscDrawLGDestroy(PetscDrawLG *lg)
379 {
380   PetscErrorCode ierr;
381   PetscInt       i;
382 
383   PetscFunctionBegin;
384   if (!*lg) PetscFunctionReturn(0);
385   if (((PetscObject)(*lg))->classid != PETSC_DRAW_CLASSID) PetscValidHeaderSpecific(*lg,PETSC_DRAWLG_CLASSID,1);
386 
387   if (--((PetscObject)(*lg))->refct > 0) {*lg = 0; PetscFunctionReturn(0);}
388   if (((PetscObject)(*lg))->classid == PETSC_DRAW_CLASSID) {
389     ierr = PetscObjectDestroy((PetscObject*)lg);CHKERRQ(ierr);
390     PetscFunctionReturn(0);
391   }
392   if ((*lg)->legend) {
393     for (i=0; i<(*lg)->dim; i++) {
394       ierr = PetscFree((*lg)->legend[i]);CHKERRQ(ierr);
395     }
396     ierr = PetscFree((*lg)->legend);CHKERRQ(ierr);
397   }
398   ierr = PetscFree((*lg)->colors);CHKERRQ(ierr);
399   ierr = PetscDrawAxisDestroy(&(*lg)->axis);CHKERRQ(ierr);
400   ierr = PetscFree2((*lg)->x,(*lg)->y);CHKERRQ(ierr);
401   ierr = PetscHeaderDestroy(lg);CHKERRQ(ierr);
402   PetscFunctionReturn(0);
403 }
404 #undef __FUNCT__
405 #define __FUNCT__ "PetscDrawLGIndicateDataPoints"
406 /*@
407    PetscDrawLGIndicateDataPoints - Causes LG to draw a big dot for each data-point.
408 
409    Not Collective, but ignored by all processors except processor 0 in PetscDrawLG
410 
411    Input Parameters:
412 .  lg - the linegraph context
413 
414    Level: intermediate
415 
416    Concepts: line graph^showing points
417 
418 @*/
419 PetscErrorCode  PetscDrawLGIndicateDataPoints(PetscDrawLG lg)
420 {
421   PetscFunctionBegin;
422   if (lg && ((PetscObject)lg)->classid == PETSC_DRAW_CLASSID) PetscFunctionReturn(0);
423 
424   lg->use_dots = PETSC_TRUE;
425   PetscFunctionReturn(0);
426 }
427 
428 #if defined(PETSC_HAVE_SETJMP_H) && defined(PETSC_HAVE_X)
429 #include <X11/Xlib.h>
430 #include <X11/Xutil.h>
431 #include <setjmp.h>
432 static jmp_buf PetscXIOErrorJumpBuf;
433 static void PetscXIOHandler(Display *dpy)
434 {
435   longjmp(PetscXIOErrorJumpBuf, 1);
436 }
437 #endif
438 
439 #undef __FUNCT__
440 #define __FUNCT__ "PetscDrawLGDraw"
441 /*@
442    PetscDrawLGDraw - Redraws a line graph.
443 
444    Not Collective,but ignored by all processors except processor 0 in PetscDrawLG
445 
446    Input Parameter:
447 .  lg - the line graph context
448 
449    Level: intermediate
450 
451 .seealso: PetscDrawSPDraw(), PetscDrawLGSPDraw()
452 
453 @*/
454 PetscErrorCode  PetscDrawLGDraw(PetscDrawLG lg)
455 {
456   PetscReal      xmin=lg->xmin,xmax=lg->xmax,ymin=lg->ymin,ymax=lg->ymax;
457   PetscErrorCode ierr;
458   int            i,j,dim = lg->dim,nopts = lg->nopts,rank,cl;
459   PetscDraw      draw = lg->win;
460   PetscBool      isnull;
461 
462   PetscFunctionBegin;
463   if (lg && ((PetscObject)lg)->classid == PETSC_DRAW_CLASSID) PetscFunctionReturn(0);
464   PetscValidHeaderSpecific(lg,PETSC_DRAWLG_CLASSID,1);
465   ierr = PetscDrawIsNull(lg->win,&isnull);CHKERRQ(ierr);
466   if (isnull) PetscFunctionReturn(0);
467 
468 #if defined(PETSC_HAVE_SETJMP_H) && defined(PETSC_HAVE_X)
469   if (!setjmp(PetscXIOErrorJumpBuf)) XSetIOErrorHandler((XIOErrorHandler)PetscXIOHandler);
470   else {
471     XSetIOErrorHandler(NULL);
472     ierr = PetscDrawSetType(draw,PETSC_DRAW_NULL);CHKERRQ(ierr);
473     PetscFunctionReturn(0);
474   }
475 #endif
476 
477   ierr = PetscDrawCheckResizedWindow(draw);CHKERRQ(ierr);
478   ierr = PetscDrawClear(draw);CHKERRQ(ierr);
479   ierr = PetscDrawAxisSetLimits(lg->axis,xmin,xmax,ymin,ymax);CHKERRQ(ierr);
480   ierr = PetscDrawAxisDraw(lg->axis);CHKERRQ(ierr);
481 
482   ierr = MPI_Comm_rank(PetscObjectComm((PetscObject)lg),&rank);CHKERRQ(ierr);
483   if (!rank) {
484 
485     for (i=0; i<dim; i++) {
486       for (j=1; j<nopts; j++) {
487         if (lg->colors) cl = lg->colors[i];
488         else cl = PETSC_DRAW_BLACK+i;
489         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);
490         if (lg->use_dots) {
491           ierr = PetscDrawString(draw,lg->x[j*dim+i],lg->y[j*dim+i],cl,"x");CHKERRQ(ierr);
492         }
493       }
494     }
495   }
496   if (lg->legend) {
497     PetscReal xl,yl,xr,yr,tw,th;
498     size_t    len,mlen = 0;
499     int       cl;
500     ierr = PetscDrawGetCoordinates(draw,&xl,&yl,&xr,&yr);CHKERRQ(ierr);
501     ierr = PetscDrawStringGetSize(draw,&tw,&th);CHKERRQ(ierr);
502     for (i=0; i<dim; i++) {
503       ierr = PetscStrlen(lg->legend[i],&len);CHKERRQ(ierr);
504       mlen = PetscMax(mlen,len);
505     }
506     ierr = PetscDrawLine(draw,xr - (mlen + 8)*tw,yr - 3*th,xr - 2*tw,yr - 3*th,PETSC_DRAW_BLACK);CHKERRQ(ierr);
507     ierr = PetscDrawLine(draw,xr - (mlen + 8)*tw,yr - 3*th,xr - (mlen + 8)*tw,yr - (4+lg->dim)*th,PETSC_DRAW_BLACK);CHKERRQ(ierr);
508     for  (i=0; i<dim; i++) {
509       cl   = (lg->colors ? lg->colors[i] : i + 1);
510       ierr = PetscDrawLine(draw,xr - (mlen + 6.7)*tw,yr - (4 + i)*th,xr - (mlen + 3.2)*tw,yr - (4 + i)*th,cl);CHKERRQ(ierr);
511       ierr = PetscDrawString(draw,xr - (mlen + 3)*tw,yr - (4.5 + i)*th,PETSC_DRAW_BLACK,lg->legend[i]);CHKERRQ(ierr);
512     }
513     ierr = PetscDrawLine(draw,xr - 2*tw,yr - 3*th,xr - 2*tw,yr - (4+lg->dim)*th,PETSC_DRAW_BLACK);CHKERRQ(ierr);
514     ierr = PetscDrawLine(draw,xr - (mlen + 8)*tw,yr - (4+lg->dim)*th,xr - 2*tw,yr - (4+lg->dim)*th,PETSC_DRAW_BLACK);CHKERRQ(ierr);
515   }
516   ierr = PetscDrawFlush(lg->win);CHKERRQ(ierr);
517   ierr = PetscDrawPause(lg->win);CHKERRQ(ierr);
518 #if defined(PETSC_HAVE_SETJMP_H) && defined(PETSC_HAVE_X)
519   XSetIOErrorHandler(NULL);
520 #endif
521   PetscFunctionReturn(0);
522 }
523 
524 #undef __FUNCT__
525 #define __FUNCT__ "PetscDrawLGView"
526 /*@
527   PetscDrawLGView - Prints a line graph.
528 
529   Not collective
530 
531   Input Parameter:
532 . lg - the line graph context
533 
534   Level: beginner
535 
536 .keywords:  draw, line, graph
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   PetscErrorCode ierr;
543 
544   PetscFunctionBegin;
545   if (lg && ((PetscObject)lg)->classid == PETSC_DRAW_CLASSID) PetscFunctionReturn(0);
546   PetscValidHeaderSpecific(lg, PETSC_DRAWLG_CLASSID,1);
547   if (nopts < 1)                  PetscFunctionReturn(0);
548   if (xmin > xmax || ymin > ymax) PetscFunctionReturn(0);
549 
550   if (!viewer){
551     ierr = PetscViewerASCIIGetStdout(PetscObjectComm((PetscObject)lg),&viewer);CHKERRQ(ierr);
552   }
553   for (i = 0; i < dim; i++) {
554     ierr = PetscViewerASCIIPrintf(viewer, "Line %D>\n", i);CHKERRQ(ierr);
555     for (j = 0; j < nopts; j++) {
556       ierr = PetscViewerASCIIPrintf(viewer, "  X: %g Y: %g\n", (double)lg->x[j*dim+i], (double)lg->y[j*dim+i]);CHKERRQ(ierr);
557     }
558   }
559   PetscFunctionReturn(0);
560 }
561