xref: /petsc/src/sys/classes/draw/utils/lgc.c (revision 67c2884ef72a42a4f3a1babc25bcfa28f347172e)
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,"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 <X11/Xlib.h>
429 #include <X11/Xutil.h>
430 #include <setjmp.h>
431 static jmp_buf PetscXIOErrorJumpBuf;
432 static void PetscXIOHandler(Display *dpy)
433 {
434   longjmp(PetscXIOErrorJumpBuf, 1);
435 }
436 #endif
437 
438 #undef __FUNCT__
439 #define __FUNCT__ "PetscDrawLGDraw"
440 /*@
441    PetscDrawLGDraw - Redraws a line graph.
442 
443    Not Collective,but ignored by all processors except processor 0 in PetscDrawLG
444 
445    Input Parameter:
446 .  lg - the line graph context
447 
448    Level: intermediate
449 
450 .seealso: PetscDrawSPDraw(), PetscDrawLGSPDraw()
451 
452 @*/
453 PetscErrorCode  PetscDrawLGDraw(PetscDrawLG lg)
454 {
455   PetscReal      xmin=lg->xmin,xmax=lg->xmax,ymin=lg->ymin,ymax=lg->ymax;
456   PetscErrorCode ierr;
457   int            i,j,dim = lg->dim,nopts = lg->nopts,rank,cl;
458   PetscDraw      draw = lg->win;
459   PetscBool      isnull;
460 
461   PetscFunctionBegin;
462   if (lg && ((PetscObject)lg)->classid == PETSC_DRAW_CLASSID) PetscFunctionReturn(0);
463   PetscValidHeaderSpecific(lg,PETSC_DRAWLG_CLASSID,1);
464   ierr = PetscDrawIsNull(lg->win,&isnull);CHKERRQ(ierr);
465   if (isnull) PetscFunctionReturn(0);
466 
467 #if defined(PETSC_HAVE_SETJMP_H) && defined(PETSC_HAVE_X)
468   if (!setjmp(PetscXIOErrorJumpBuf)) XSetIOErrorHandler((XIOErrorHandler)PetscXIOHandler);
469   else {
470     XSetIOErrorHandler(NULL);
471     ierr = PetscDrawSetType(draw,PETSC_DRAW_NULL);CHKERRQ(ierr);
472     PetscFunctionReturn(0);
473   }
474 #endif
475 
476   ierr = PetscDrawCheckResizedWindow(draw);CHKERRQ(ierr);
477   ierr = PetscDrawClear(draw);CHKERRQ(ierr);
478   ierr = PetscDrawAxisSetLimits(lg->axis,xmin,xmax,ymin,ymax);CHKERRQ(ierr);
479   ierr = PetscDrawAxisDraw(lg->axis);CHKERRQ(ierr);
480 
481   ierr = MPI_Comm_rank(((PetscObject)lg)->comm,&rank);CHKERRQ(ierr);
482   if (!rank) {
483 
484     for (i=0; i<dim; i++) {
485       for (j=1; j<nopts; j++) {
486         if (lg->colors) cl = lg->colors[i];
487         else cl = PETSC_DRAW_BLACK+i;
488         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);
489         if (lg->use_dots) {
490           ierr = PetscDrawString(draw,lg->x[j*dim+i],lg->y[j*dim+i],cl,"x");CHKERRQ(ierr);
491         }
492       }
493     }
494   }
495   if (lg->legend) {
496     PetscReal xl,yl,xr,yr,tw,th;
497     size_t    len,mlen = 0;
498     int       cl;
499     ierr = PetscDrawGetCoordinates(draw,&xl,&yl,&xr,&yr);CHKERRQ(ierr);
500     ierr = PetscDrawStringGetSize(draw,&tw,&th);CHKERRQ(ierr);
501     for (i=0; i<dim; i++) {
502       ierr = PetscStrlen(lg->legend[i],&len);CHKERRQ(ierr);
503       mlen = PetscMax(mlen,len);
504     }
505     ierr = PetscDrawLine(draw,xr - (mlen + 8)*tw,yr - 3*th,xr - 2*tw,yr - 3*th,PETSC_DRAW_BLACK);CHKERRQ(ierr);
506     ierr = PetscDrawLine(draw,xr - (mlen + 8)*tw,yr - 3*th,xr - (mlen + 8)*tw,yr - (4+lg->dim)*th,PETSC_DRAW_BLACK);CHKERRQ(ierr);
507     for  (i=0; i<dim; i++) {
508       cl   = (lg->colors ? lg->colors[i] : i + 1);
509       ierr = PetscDrawLine(draw,xr - (mlen + 6.7)*tw,yr - (4 + i)*th,xr - (mlen + 3.2)*tw,yr - (4 + i)*th,cl);CHKERRQ(ierr);
510       ierr = PetscDrawString(draw,xr - (mlen + 3)*tw,yr - (4.5 + i)*th,PETSC_DRAW_BLACK,lg->legend[i]);CHKERRQ(ierr);
511     }
512     ierr = PetscDrawLine(draw,xr - 2*tw,yr - 3*th,xr - 2*tw,yr - (4+lg->dim)*th,PETSC_DRAW_BLACK);CHKERRQ(ierr);
513     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);
514   }
515   ierr = PetscDrawFlush(lg->win);CHKERRQ(ierr);
516   ierr = PetscDrawPause(lg->win);CHKERRQ(ierr);
517 #if defined(PETSC_HAVE_SETJMP_H) && defined(PETSC_HAVE_X)
518   XSetIOErrorHandler(NULL);
519 #endif
520   PetscFunctionReturn(0);
521 }
522 
523 #undef __FUNCT__
524 #define __FUNCT__ "PetscDrawLGPrint"
525 /*@
526   PetscDrawLGPrint - Prints a line graph.
527 
528   Not collective
529 
530   Input Parameter:
531 . lg - the line graph context
532 
533   Level: beginner
534 
535   Contributed by Matthew Knepley
536 
537 .keywords:  draw, line, graph
538 @*/
539 PetscErrorCode  PetscDrawLGPrint(PetscDrawLG lg)
540 {
541   PetscReal xmin=lg->xmin, xmax=lg->xmax, ymin=lg->ymin, ymax=lg->ymax;
542   int       i, j, dim = lg->dim, nopts = lg->nopts;
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   for (i = 0; i < dim; i++) {
551     PetscPrintf(((PetscObject)lg)->comm, "Line %d>\n", i);
552     for (j = 0; j < nopts; j++) {
553       PetscPrintf(((PetscObject)lg)->comm, "  X: %g Y: %g\n", (double)lg->x[j*dim+i], (double)lg->y[j*dim+i]);
554     }
555   }
556   PetscFunctionReturn(0);
557 }
558