xref: /petsc/src/sys/classes/draw/utils/lgc.c (revision 5c8f6a953e7ed1c81f507d64aebddb11080b60e9)
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) {
59     *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(((PetscObject)lg)->comm,&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(((PetscObject)obj)->comm,(PetscDraw*)outctx);CHKERRQ(ierr);
168     PetscFunctionReturn(0);
169   }
170   ierr = PetscHeaderCreate(lg,_p_PetscDrawLG,int,PETSC_DRAWLG_CLASSID,0,"PetscDrawLG","Line graph","Draw",((PetscObject)obj)->comm,PetscDrawLGDestroy,0);CHKERRQ(ierr);
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   ierr = PetscMalloc2(dim*CHUNCKSIZE,PetscReal,&lg->x,dim*CHUNCKSIZE,PetscReal,&lg->y);CHKERRQ(ierr);
181   ierr = PetscLogObjectMemory(lg,2*dim*CHUNCKSIZE*sizeof(PetscReal));CHKERRQ(ierr);
182   lg->len     = dim*CHUNCKSIZE;
183   lg->loc     = 0;
184   lg->use_dots= PETSC_FALSE;
185   ierr = PetscDrawAxisCreate(draw,&lg->axis);CHKERRQ(ierr);
186   ierr = PetscLogObjectParent(lg,lg->axis);CHKERRQ(ierr);
187   *outctx = lg;
188   PetscFunctionReturn(0);
189 }
190 
191 #undef __FUNCT__
192 #define __FUNCT__ "PetscDrawLGSetColors"
193 /*@
194    PetscDrawLGSetColors - Sets the color of each line graph drawn
195 
196    Logically Collective over PetscDrawLG
197 
198    Input Parameter:
199 +  lg - the line graph context.
200 -  colors - the colors
201 
202    Level: intermediate
203 
204    Concepts: line graph^setting number of lines
205 
206 @*/
207 PetscErrorCode  PetscDrawLGSetColors(PetscDrawLG lg,const int *colors)
208 {
209   PetscErrorCode ierr;
210 
211   PetscFunctionBegin;
212   if (lg && ((PetscObject)lg)->classid == PETSC_DRAW_CLASSID) PetscFunctionReturn(0);
213   PetscValidHeaderSpecific(lg,PETSC_DRAWLG_CLASSID,1);
214   ierr = PetscFree(lg->colors);CHKERRQ(ierr);
215   ierr = PetscMalloc(lg->dim*sizeof(int),&lg->colors);CHKERRQ(ierr);
216   ierr = PetscMemcpy(lg->colors,colors,lg->dim*sizeof(int));CHKERRQ(ierr);
217   PetscFunctionReturn(0);
218 }
219 
220 #undef __FUNCT__
221 #undef __FUNCT__
222 #define __FUNCT__ "PetscDrawLGSetLegend"
223 /*@C
224    PetscDrawLGSetLegend - sets the names of each curve plotted
225 
226    Logically Collective over PetscDrawLG
227 
228    Input Parameter:
229 +  lg - the line graph context.
230 -  names - the names for each curve
231 
232    Level: intermediate
233 
234    Concepts: line graph^setting number of lines
235 
236 @*/
237 PetscErrorCode  PetscDrawLGSetLegend(PetscDrawLG lg,const char *const *names)
238 {
239   PetscErrorCode ierr;
240   PetscInt       i;
241 
242   PetscFunctionBegin;
243   if (lg && ((PetscObject)lg)->classid == PETSC_DRAW_CLASSID) PetscFunctionReturn(0);
244   PetscValidHeaderSpecific(lg,PETSC_DRAWLG_CLASSID,1);
245 
246   if (lg->legend) {
247     for (i=0; i<lg->dim; i++) {
248       ierr = PetscFree(lg->legend[i]);CHKERRQ(ierr);
249     }
250     ierr = PetscFree(lg->legend);CHKERRQ(ierr);
251   }
252   if (names) {
253     ierr = PetscMalloc(lg->dim*sizeof(char**),&lg->legend);CHKERRQ(ierr);
254     for (i=0; i<lg->dim; i++) {
255       ierr = PetscStrallocpy(names[i],&lg->legend[i]);CHKERRQ(ierr);
256     }
257   }
258   PetscFunctionReturn(0);
259 }
260 
261 #undef __FUNCT__
262 #define __FUNCT__ "PetscDrawLGGetDimension"
263 /*@
264    PetscDrawLGGetDimension - Change the number of lines that are to be drawn.
265 
266    Logically Collective over PetscDrawLG
267 
268    Input Parameter:
269 .  lg - the line graph context.
270 
271    Output Parameter:
272 .  dim - the number of curves.
273 
274    Level: intermediate
275 
276    Concepts: line graph^setting number of lines
277 
278 @*/
279 PetscErrorCode  PetscDrawLGGetDimension(PetscDrawLG lg,PetscInt *dim)
280 {
281   PetscFunctionBegin;
282   if (lg && ((PetscObject)lg)->classid == PETSC_DRAW_CLASSID) PetscFunctionReturn(0);
283   PetscValidHeaderSpecific(lg,PETSC_DRAWLG_CLASSID,1);
284   *dim = lg->dim;
285   PetscFunctionReturn(0);
286 }
287 
288 #undef __FUNCT__
289 #define __FUNCT__ "PetscDrawLGSetDimension"
290 /*@
291    PetscDrawLGSetDimension - Change the number of lines that are to be drawn.
292 
293    Logically Collective over PetscDrawLG
294 
295    Input Parameter:
296 +  lg - the line graph context.
297 -  dim - the number of curves.
298 
299    Level: intermediate
300 
301    Concepts: line graph^setting number of lines
302 
303 @*/
304 PetscErrorCode  PetscDrawLGSetDimension(PetscDrawLG lg,PetscInt dim)
305 {
306   PetscErrorCode ierr;
307   PetscInt       i;
308 
309   PetscFunctionBegin;
310   if (lg && ((PetscObject)lg)->classid == PETSC_DRAW_CLASSID) PetscFunctionReturn(0);
311   PetscValidHeaderSpecific(lg,PETSC_DRAWLG_CLASSID,1);
312   PetscValidLogicalCollectiveInt(lg,dim,2);
313   if (lg->dim == dim) PetscFunctionReturn(0);
314 
315   ierr    = PetscFree2(lg->x,lg->y);CHKERRQ(ierr);
316   if (lg->legend) {
317     for (i=0; i<lg->dim; i++) {
318       ierr = PetscFree(lg->legend[i]);CHKERRQ(ierr);
319     }
320     ierr = PetscFree(lg->legend);CHKERRQ(ierr);
321   }
322   ierr = PetscFree(lg->colors);CHKERRQ(ierr);
323   lg->dim = dim;
324   ierr    = PetscMalloc2(dim*CHUNCKSIZE,PetscReal,&lg->x,dim*CHUNCKSIZE,PetscReal,&lg->y);CHKERRQ(ierr);
325   ierr = PetscLogObjectMemory(lg,2*dim*CHUNCKSIZE*sizeof(PetscReal));CHKERRQ(ierr);
326   lg->len     = dim*CHUNCKSIZE;
327   PetscFunctionReturn(0);
328 }
329 
330 #undef __FUNCT__
331 #define __FUNCT__ "PetscDrawLGReset"
332 /*@
333    PetscDrawLGReset - Clears line graph to allow for reuse with new data.
334 
335    Logically Collective over PetscDrawLG
336 
337    Input Parameter:
338 .  lg - the line graph context.
339 
340    Level: intermediate
341 
342    Concepts: line graph^restarting
343 
344 @*/
345 PetscErrorCode  PetscDrawLGReset(PetscDrawLG lg)
346 {
347   PetscFunctionBegin;
348   if (lg && ((PetscObject)lg)->classid == PETSC_DRAW_CLASSID) PetscFunctionReturn(0);
349   PetscValidHeaderSpecific(lg,PETSC_DRAWLG_CLASSID,1);
350   lg->xmin  = 1.e20;
351   lg->ymin  = 1.e20;
352   lg->xmax  = -1.e20;
353   lg->ymax  = -1.e20;
354   lg->loc   = 0;
355   lg->nopts = 0;
356   PetscFunctionReturn(0);
357 }
358 
359 #undef __FUNCT__
360 #define __FUNCT__ "PetscDrawLGDestroy"
361 /*@
362    PetscDrawLGDestroy - Frees all space taken up by line graph data structure.
363 
364    Collective over PetscDrawLG
365 
366    Input Parameter:
367 .  lg - the line graph context
368 
369    Level: intermediate
370 
371 .seealso:  PetscDrawLGCreate()
372 @*/
373 PetscErrorCode  PetscDrawLGDestroy(PetscDrawLG *lg)
374 {
375   PetscErrorCode ierr;
376   PetscInt       i;
377 
378   PetscFunctionBegin;
379   if (!*lg) PetscFunctionReturn(0);
380   if (((PetscObject)(*lg))->classid != PETSC_DRAW_CLASSID) {
381     PetscValidHeaderSpecific(*lg,PETSC_DRAWLG_CLASSID,1);
382   }
383 
384   if (--((PetscObject)(*lg))->refct > 0) {*lg = 0; PetscFunctionReturn(0);}
385   if (((PetscObject)(*lg))->classid == PETSC_DRAW_CLASSID) {
386     ierr = PetscObjectDestroy((PetscObject*)lg);CHKERRQ(ierr);
387     PetscFunctionReturn(0);
388   }
389   if ((*lg)->legend) {
390     for (i=0; i<(*lg)->dim; i++) {
391       ierr = PetscFree((*lg)->legend[i]);CHKERRQ(ierr);
392     }
393     ierr = PetscFree((*lg)->legend);CHKERRQ(ierr);
394   }
395   ierr = PetscFree((*lg)->colors);CHKERRQ(ierr);
396   ierr = PetscDrawAxisDestroy(&(*lg)->axis);CHKERRQ(ierr);
397   ierr = PetscFree2((*lg)->x,(*lg)->y);CHKERRQ(ierr);
398   ierr = PetscHeaderDestroy(lg);CHKERRQ(ierr);
399   PetscFunctionReturn(0);
400 }
401 #undef __FUNCT__
402 #define __FUNCT__ "PetscDrawLGIndicateDataPoints"
403 /*@
404    PetscDrawLGIndicateDataPoints - Causes LG to draw a big dot for each data-point.
405 
406    Not Collective, but ignored by all processors except processor 0 in PetscDrawLG
407 
408    Input Parameters:
409 .  lg - the linegraph context
410 
411    Level: intermediate
412 
413    Concepts: line graph^showing points
414 
415 @*/
416 PetscErrorCode  PetscDrawLGIndicateDataPoints(PetscDrawLG lg)
417 {
418   PetscFunctionBegin;
419   if (lg && ((PetscObject)lg)->classid == PETSC_DRAW_CLASSID) PetscFunctionReturn(0);
420 
421   lg->use_dots = PETSC_TRUE;
422   PetscFunctionReturn(0);
423 }
424 
425 #if defined(PETSC_HAVE_SETJMP_H) && defined(PETSC_HAVE_X)
426 #include <sys/types.h>
427 #include <X11/Xlib.h>
428 #include <X11/Xutil.h>
429 #include <setjmp.h>
430 static jmp_buf PetscXIOErrorJumpBuf;
431 static void PetscXIOHandler(Display *dpy)
432 {
433   longjmp(PetscXIOErrorJumpBuf, 1);
434 }
435 #endif
436 
437 #undef __FUNCT__
438 #define __FUNCT__ "PetscDrawLGDraw"
439 /*@
440    PetscDrawLGDraw - Redraws a line graph.
441 
442    Not Collective,but ignored by all processors except processor 0 in PetscDrawLG
443 
444    Input Parameter:
445 .  lg - the line graph context
446 
447    Level: intermediate
448 
449 .seealso: PetscDrawSPDraw(), PetscDrawLGSPDraw()
450 
451 @*/
452 PetscErrorCode  PetscDrawLGDraw(PetscDrawLG lg)
453 {
454   PetscReal      xmin=lg->xmin,xmax=lg->xmax,ymin=lg->ymin,ymax=lg->ymax;
455   PetscErrorCode ierr;
456   int            i,j,dim = lg->dim,nopts = lg->nopts,rank,cl;
457   PetscDraw      draw = lg->win;
458   PetscBool      isnull;
459 
460   PetscFunctionBegin;
461   if (lg && ((PetscObject)lg)->classid == PETSC_DRAW_CLASSID) PetscFunctionReturn(0);
462   PetscValidHeaderSpecific(lg,PETSC_DRAWLG_CLASSID,1);
463   ierr = PetscDrawIsNull(lg->win,&isnull);CHKERRQ(ierr);
464   if (isnull) PetscFunctionReturn(0);
465 
466 #if defined(PETSC_HAVE_SETJMP_H) && defined(PETSC_HAVE_X)
467   if (!setjmp(PetscXIOErrorJumpBuf)) XSetIOErrorHandler((XIOErrorHandler)PetscXIOHandler);
468   else {
469     XSetIOErrorHandler(PETSC_NULL);
470     ierr = PetscDrawSetType(draw,PETSC_DRAW_NULL);CHKERRQ(ierr);
471     PetscFunctionReturn(0);
472   }
473 #endif
474 
475   ierr = PetscDrawCheckResizedWindow(draw);CHKERRQ(ierr);
476   ierr = PetscDrawClear(draw);CHKERRQ(ierr);
477   ierr = PetscDrawAxisSetLimits(lg->axis,xmin,xmax,ymin,ymax);CHKERRQ(ierr);
478   ierr = PetscDrawAxisDraw(lg->axis);CHKERRQ(ierr);
479 
480   ierr = MPI_Comm_rank(((PetscObject)lg)->comm,&rank);CHKERRQ(ierr);
481   if (!rank) {
482 
483     for (i=0; i<dim; i++) {
484       for (j=1; j<nopts; j++) {
485         if (lg->colors) cl = lg->colors[i];
486         else cl = PETSC_DRAW_BLACK+i;
487         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);
488         if (lg->use_dots) {
489           ierr = PetscDrawString(draw,lg->x[j*dim+i],lg->y[j*dim+i],cl,"x");CHKERRQ(ierr);
490         }
491       }
492     }
493   }
494   if (lg->legend) {
495     PetscReal xl,yl,xr,yr,tw,th;
496     size_t    len,mlen = 0;
497     int       cl;
498     ierr = PetscDrawGetCoordinates(draw,&xl,&yl,&xr,&yr);CHKERRQ(ierr);
499     ierr = PetscDrawStringGetSize(draw,&tw,&th);CHKERRQ(ierr);
500     for (i=0; i<dim; i++) {
501       ierr = PetscStrlen(lg->legend[i],&len);CHKERRQ(ierr);
502       mlen = PetscMax(mlen,len);
503     }
504     ierr = PetscDrawLine(draw,xr - (mlen + 8)*tw,yr - 3*th,xr - 2*tw,yr - 3*th,PETSC_DRAW_BLACK);CHKERRQ(ierr);
505     ierr = PetscDrawLine(draw,xr - (mlen + 8)*tw,yr - 3*th,xr - (mlen + 8)*tw,yr - (4+lg->dim)*th,PETSC_DRAW_BLACK);CHKERRQ(ierr);
506     for  (i=0; i<dim; i++) {
507       cl = (lg->colors ? lg->colors[i] : i + 1);
508       ierr = PetscDrawLine(draw,xr - (mlen + 6.7)*tw,yr - (4 + i)*th,xr - (mlen + 3.2)*tw,yr - (4 + i)*th,cl);CHKERRQ(ierr);
509       ierr = PetscDrawString(draw,xr - (mlen + 3)*tw,yr - (4.5 + i)*th,PETSC_DRAW_BLACK,lg->legend[i]);CHKERRQ(ierr);
510     }
511     ierr = PetscDrawLine(draw,xr - 2*tw,yr - 3*th,xr - 2*tw,yr - (4+lg->dim)*th,PETSC_DRAW_BLACK);CHKERRQ(ierr);
512     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);
513   }
514   ierr = PetscDrawFlush(lg->win);CHKERRQ(ierr);
515   ierr = PetscDrawPause(lg->win);CHKERRQ(ierr);
516 #if defined(PETSC_HAVE_SETJMP_H) && defined(PETSC_HAVE_X)
517   XSetIOErrorHandler(PETSC_NULL);
518 #endif
519   PetscFunctionReturn(0);
520 }
521 
522 #undef __FUNCT__
523 #define __FUNCT__ "PetscDrawLGPrint"
524 /*@
525   PetscDrawLGPrint - Prints a line graph.
526 
527   Not collective
528 
529   Input Parameter:
530 . lg - the line graph context
531 
532   Level: beginner
533 
534   Contributed by Matthew Knepley
535 
536 .keywords:  draw, line, graph
537 @*/
538 PetscErrorCode  PetscDrawLGPrint(PetscDrawLG lg)
539 {
540   PetscReal xmin=lg->xmin, xmax=lg->xmax, ymin=lg->ymin, ymax=lg->ymax;
541   int       i, j, dim = lg->dim, nopts = lg->nopts;
542 
543   PetscFunctionBegin;
544   if (lg && ((PetscObject)lg)->classid == PETSC_DRAW_CLASSID) PetscFunctionReturn(0);
545   PetscValidHeaderSpecific(lg, PETSC_DRAWLG_CLASSID,1);
546   if (nopts < 1)                  PetscFunctionReturn(0);
547   if (xmin > xmax || ymin > ymax) PetscFunctionReturn(0);
548 
549   for (i = 0; i < dim; i++) {
550     PetscPrintf(((PetscObject)lg)->comm, "Line %d>\n", i);
551     for (j = 0; j < nopts; j++) {
552       PetscPrintf(((PetscObject)lg)->comm, "  X: %g Y: %g\n", (double)lg->x[j*dim+i], (double)lg->y[j*dim+i]);
553     }
554   }
555   PetscFunctionReturn(0);
556 }
557