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