Actual source code: lgc.c

petsc-3.4.4 2014-03-13
  2: #include <../src/sys/classes/draw/utils/lgimpl.h>  /*I   "petscdraw.h"  I*/
  3: #include <petscviewer.h>
  4: PetscClassId PETSC_DRAWLG_CLASSID = 0;

  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.

 14:    Not Collective, if PetscDrawLG is parallel then PetscDrawAxis is parallel

 16:    Input Parameter:
 17: .  lg - the line graph context

 19:    Output Parameter:
 20: .  axis - the axis context

 22:    Level: advanced

 24: @*/
 25: PetscErrorCode  PetscDrawLGGetAxis(PetscDrawLG lg,PetscDrawAxis *axis)
 26: {
 28:   if (lg && ((PetscObject)lg)->classid == PETSC_DRAW_CLASSID) {
 29:     *axis = 0;
 30:     return(0);
 31:   }
 34:   *axis = lg->axis;
 35:   return(0);
 36: }

 40: /*@
 41:    PetscDrawLGGetDraw - Gets the draw context associated with a line graph.

 43:    Not Collective, if PetscDrawLG is parallel then PetscDraw is parallel

 45:    Input Parameter:
 46: .  lg - the line graph context

 48:    Output Parameter:
 49: .  draw - the draw context

 51:    Level: intermediate

 53: @*/
 54: PetscErrorCode  PetscDrawLGGetDraw(PetscDrawLG lg,PetscDraw *draw)
 55: {
 59:   if (((PetscObject)lg)->classid == PETSC_DRAW_CLASSID) *draw = (PetscDraw)lg;
 60:   else {
 62:     *draw = lg->win;
 63:   }
 64:   return(0);
 65: }


 70: /*@
 71:    PetscDrawLGSPDraw - Redraws a line graph.

 73:    Not Collective,but ignored by all processors except processor 0 in PetscDrawLG

 75:    Input Parameter:
 76: .  lg - the line graph context

 78:    Level: intermediate

 80: .seealso: PetscDrawLGDraw(), PetscDrawSPDraw()

 82:    Developer Notes: This code cheats and uses the fact that the LG and SP structs are the same

 84: @*/
 85: PetscErrorCode  PetscDrawLGSPDraw(PetscDrawLG lg,PetscDrawSP spin)
 86: {
 87:   PetscDrawLG    sp = (PetscDrawLG)spin;
 88:   PetscReal      xmin,xmax,ymin,ymax;
 90:   int            i,j,dim,nopts,rank;
 91:   PetscDraw      draw = lg->win;

 94:   if (lg && ((PetscObject)lg)->classid == PETSC_DRAW_CLASSID) return(0);

 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);

103:   PetscDrawClear(draw);
104:   PetscDrawAxisSetLimits(lg->axis,xmin,xmax,ymin,ymax);
105:   PetscDrawAxisDraw(lg->axis);

107:   MPI_Comm_rank(PetscObjectComm((PetscObject)lg),&rank);
108:   if (!rank) {

110:     dim   = lg->dim;
111:     nopts = lg->nopts;
112:     for (i=0; i<dim; i++) {
113:       for (j=1; j<nopts; j++) {
114:         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);
115:         if (lg->use_dots) {
116:           PetscDrawString(draw,lg->x[j*dim+i],lg->y[j*dim+i],PETSC_DRAW_RED,"x");
117:         }
118:       }
119:     }

121:     dim   = sp->dim;
122:     nopts = sp->nopts;
123:     for (i=0; i<dim; i++) {
124:       for (j=0; j<nopts; j++) {
125:         PetscDrawString(draw,sp->x[j*dim+i],sp->y[j*dim+i],PETSC_DRAW_RED,"x");
126:       }
127:     }
128:   }
129:   PetscDrawFlush(lg->win);
130:   PetscDrawPause(lg->win);
131:   return(0);
132: }


137: /*@
138:     PetscDrawLGCreate - Creates a line graph data structure.

140:     Collective over PetscDraw

142:     Input Parameters:
143: +   draw - the window where the graph will be made.
144: -   dim - the number of curves which will be drawn

146:     Output Parameters:
147: .   outctx - the line graph context

149:     Level: intermediate

151:     Concepts: line graph^creating

153: .seealso:  PetscDrawLGDestroy()
154: @*/
155: PetscErrorCode  PetscDrawLGCreate(PetscDraw draw,PetscInt dim,PetscDrawLG *outctx)
156: {
158:   PetscBool      isnull;
159:   PetscObject    obj = (PetscObject)draw;
160:   PetscDrawLG    lg;

165:   PetscObjectTypeCompare(obj,PETSC_DRAW_NULL,&isnull);
166:   if (isnull) {
167:     PetscDrawOpenNull(PetscObjectComm((PetscObject)obj),(PetscDraw*)outctx);
168:     return(0);
169:   }
170:   PetscHeaderCreate(lg,_p_PetscDrawLG,int,PETSC_DRAWLG_CLASSID,"PetscDrawLG","Line graph","Draw",PetscObjectComm((PetscObject)obj),PetscDrawLGDestroy,0);

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;

182:   PetscMalloc2(dim*CHUNCKSIZE,PetscReal,&lg->x,dim*CHUNCKSIZE,PetscReal,&lg->y);
183:   PetscLogObjectMemory(lg,2*dim*CHUNCKSIZE*sizeof(PetscReal));

185:   lg->len     = dim*CHUNCKSIZE;
186:   lg->loc     = 0;
187:   lg->use_dots= PETSC_FALSE;

189:   PetscDrawAxisCreate(draw,&lg->axis);
190:   PetscLogObjectParent(lg,lg->axis);

192:   *outctx = lg;
193:   return(0);
194: }

198: /*@
199:    PetscDrawLGSetColors - Sets the color of each line graph drawn

201:    Logically Collective over PetscDrawLG

203:    Input Parameter:
204: +  lg - the line graph context.
205: -  colors - the colors

207:    Level: intermediate

209:    Concepts: line graph^setting number of lines

211: @*/
212: PetscErrorCode  PetscDrawLGSetColors(PetscDrawLG lg,const int *colors)
213: {

217:   if (lg && ((PetscObject)lg)->classid == PETSC_DRAW_CLASSID) return(0);
219:   PetscFree(lg->colors);
220:   PetscMalloc(lg->dim*sizeof(int),&lg->colors);
221:   PetscMemcpy(lg->colors,colors,lg->dim*sizeof(int));
222:   return(0);
223: }

228: /*@C
229:    PetscDrawLGSetLegend - sets the names of each curve plotted

231:    Logically Collective over PetscDrawLG

233:    Input Parameter:
234: +  lg - the line graph context.
235: -  names - the names for each curve

237:    Level: intermediate

239:    Concepts: line graph^setting number of lines

241: @*/
242: PetscErrorCode  PetscDrawLGSetLegend(PetscDrawLG lg,const char *const *names)
243: {
245:   PetscInt       i;

248:   if (lg && ((PetscObject)lg)->classid == PETSC_DRAW_CLASSID) return(0);

251:   if (lg->legend) {
252:     for (i=0; i<lg->dim; i++) {
253:       PetscFree(lg->legend[i]);
254:     }
255:     PetscFree(lg->legend);
256:   }
257:   if (names) {
258:     PetscMalloc(lg->dim*sizeof(char**),&lg->legend);
259:     for (i=0; i<lg->dim; i++) {
260:       PetscStrallocpy(names[i],&lg->legend[i]);
261:     }
262:   }
263:   return(0);
264: }

268: /*@
269:    PetscDrawLGGetDimension - Change the number of lines that are to be drawn.

271:    Logically Collective over PetscDrawLG

273:    Input Parameter:
274: .  lg - the line graph context.

276:    Output Parameter:
277: .  dim - the number of curves.

279:    Level: intermediate

281:    Concepts: line graph^setting number of lines

283: @*/
284: PetscErrorCode  PetscDrawLGGetDimension(PetscDrawLG lg,PetscInt *dim)
285: {
287:   if (lg && ((PetscObject)lg)->classid == PETSC_DRAW_CLASSID) return(0);
289:   *dim = lg->dim;
290:   return(0);
291: }

295: /*@
296:    PetscDrawLGSetDimension - Change the number of lines that are to be drawn.

298:    Logically Collective over PetscDrawLG

300:    Input Parameter:
301: +  lg - the line graph context.
302: -  dim - the number of curves.

304:    Level: intermediate

306:    Concepts: line graph^setting number of lines

308: @*/
309: PetscErrorCode  PetscDrawLGSetDimension(PetscDrawLG lg,PetscInt dim)
310: {
312:   PetscInt       i;

315:   if (lg && ((PetscObject)lg)->classid == PETSC_DRAW_CLASSID) return(0);
318:   if (lg->dim == dim) return(0);

320:   PetscFree2(lg->x,lg->y);
321:   if (lg->legend) {
322:     for (i=0; i<lg->dim; i++) {
323:       PetscFree(lg->legend[i]);
324:     }
325:     PetscFree(lg->legend);
326:   }
327:   PetscFree(lg->colors);
328:   lg->dim = dim;
329:   PetscMalloc2(dim*CHUNCKSIZE,PetscReal,&lg->x,dim*CHUNCKSIZE,PetscReal,&lg->y);
330:   PetscLogObjectMemory(lg,2*dim*CHUNCKSIZE*sizeof(PetscReal));
331:   lg->len = dim*CHUNCKSIZE;
332:   return(0);
333: }

337: /*@
338:    PetscDrawLGReset - Clears line graph to allow for reuse with new data.

340:    Logically Collective over PetscDrawLG

342:    Input Parameter:
343: .  lg - the line graph context.

345:    Level: intermediate

347:    Concepts: line graph^restarting

349: @*/
350: PetscErrorCode  PetscDrawLGReset(PetscDrawLG lg)
351: {
353:   if (lg && ((PetscObject)lg)->classid == PETSC_DRAW_CLASSID) return(0);
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:   return(0);
362: }

366: /*@
367:    PetscDrawLGDestroy - Frees all space taken up by line graph data structure.

369:    Collective over PetscDrawLG

371:    Input Parameter:
372: .  lg - the line graph context

374:    Level: intermediate

376: .seealso:  PetscDrawLGCreate()
377: @*/
378: PetscErrorCode  PetscDrawLGDestroy(PetscDrawLG *lg)
379: {
381:   PetscInt       i;

384:   if (!*lg) return(0);

387:   if (--((PetscObject)(*lg))->refct > 0) {*lg = 0; return(0);}
388:   if (((PetscObject)(*lg))->classid == PETSC_DRAW_CLASSID) {
389:     PetscObjectDestroy((PetscObject*)lg);
390:     return(0);
391:   }
392:   if ((*lg)->legend) {
393:     for (i=0; i<(*lg)->dim; i++) {
394:       PetscFree((*lg)->legend[i]);
395:     }
396:     PetscFree((*lg)->legend);
397:   }
398:   PetscFree((*lg)->colors);
399:   PetscDrawAxisDestroy(&(*lg)->axis);
400:   PetscFree2((*lg)->x,(*lg)->y);
401:   PetscHeaderDestroy(lg);
402:   return(0);
403: }
406: /*@
407:    PetscDrawLGIndicateDataPoints - Causes LG to draw a big dot for each data-point.

409:    Not Collective, but ignored by all processors except processor 0 in PetscDrawLG

411:    Input Parameters:
412: .  lg - the linegraph context

414:    Level: intermediate

416:    Concepts: line graph^showing points

418: @*/
419: PetscErrorCode  PetscDrawLGIndicateDataPoints(PetscDrawLG lg)
420: {
422:   if (lg && ((PetscObject)lg)->classid == PETSC_DRAW_CLASSID) return(0);

424:   lg->use_dots = PETSC_TRUE;
425:   return(0);
426: }

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

441: /*@
442:    PetscDrawLGDraw - Redraws a line graph.

444:    Not Collective,but ignored by all processors except processor 0 in PetscDrawLG

446:    Input Parameter:
447: .  lg - the line graph context

449:    Level: intermediate

451: .seealso: PetscDrawSPDraw(), PetscDrawLGSPDraw()

453: @*/
454: PetscErrorCode  PetscDrawLGDraw(PetscDrawLG lg)
455: {
456:   PetscReal      xmin=lg->xmin,xmax=lg->xmax,ymin=lg->ymin,ymax=lg->ymax;
458:   int            i,j,dim = lg->dim,nopts = lg->nopts,rank,cl;
459:   PetscDraw      draw = lg->win;
460:   PetscBool      isnull;

463:   if (lg && ((PetscObject)lg)->classid == PETSC_DRAW_CLASSID) return(0);
465:   PetscDrawIsNull(lg->win,&isnull);
466:   if (isnull) return(0);

468: #if defined(PETSC_HAVE_SETJMP_H) && defined(PETSC_HAVE_X)
469:   if (!setjmp(PetscXIOErrorJumpBuf)) XSetIOErrorHandler((XIOErrorHandler)PetscXIOHandler);
470:   else {
471:     XSetIOErrorHandler(NULL);
472:     PetscDrawSetType(draw,PETSC_DRAW_NULL);
473:     return(0);
474:   }
475: #endif

477:   PetscDrawCheckResizedWindow(draw);
478:   PetscDrawClear(draw);
479:   PetscDrawAxisSetLimits(lg->axis,xmin,xmax,ymin,ymax);
480:   PetscDrawAxisDraw(lg->axis);

482:   MPI_Comm_rank(PetscObjectComm((PetscObject)lg),&rank);
483:   if (!rank) {

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:         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);
490:         if (lg->use_dots) {
491:           PetscDrawString(draw,lg->x[j*dim+i],lg->y[j*dim+i],cl,"x");
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:     PetscDrawGetCoordinates(draw,&xl,&yl,&xr,&yr);
501:     PetscDrawStringGetSize(draw,&tw,&th);
502:     for (i=0; i<dim; i++) {
503:       PetscStrlen(lg->legend[i],&len);
504:       mlen = PetscMax(mlen,len);
505:     }
506:     PetscDrawLine(draw,xr - (mlen + 8)*tw,yr - 3*th,xr - 2*tw,yr - 3*th,PETSC_DRAW_BLACK);
507:     PetscDrawLine(draw,xr - (mlen + 8)*tw,yr - 3*th,xr - (mlen + 8)*tw,yr - (4+lg->dim)*th,PETSC_DRAW_BLACK);
508:     for  (i=0; i<dim; i++) {
509:       cl   = (lg->colors ? lg->colors[i] : i + 1);
510:       PetscDrawLine(draw,xr - (mlen + 6.7)*tw,yr - (4 + i)*th,xr - (mlen + 3.2)*tw,yr - (4 + i)*th,cl);
511:       PetscDrawString(draw,xr - (mlen + 3)*tw,yr - (4.5 + i)*th,PETSC_DRAW_BLACK,lg->legend[i]);
512:     }
513:     PetscDrawLine(draw,xr - 2*tw,yr - 3*th,xr - 2*tw,yr - (4+lg->dim)*th,PETSC_DRAW_BLACK);
514:     PetscDrawLine(draw,xr - (mlen + 8)*tw,yr - (4+lg->dim)*th,xr - 2*tw,yr - (4+lg->dim)*th,PETSC_DRAW_BLACK);
515:   }
516:   PetscDrawFlush(lg->win);
517:   PetscDrawPause(lg->win);
518: #if defined(PETSC_HAVE_SETJMP_H) && defined(PETSC_HAVE_X)
519:   XSetIOErrorHandler(NULL);
520: #endif
521:   return(0);
522: }

526: /*@
527:   PetscDrawLGView - Prints a line graph.

529:   Not collective

531:   Input Parameter:
532: . lg - the line graph context

534:   Level: beginner

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;

545:   if (lg && ((PetscObject)lg)->classid == PETSC_DRAW_CLASSID) return(0);
547:   if (nopts < 1)                  return(0);
548:   if (xmin > xmax || ymin > ymax) return(0);

550:   if (!viewer){
551:     PetscViewerASCIIGetStdout(PetscObjectComm((PetscObject)lg),&viewer);
552:   }
553:   for (i = 0; i < dim; i++) {
554:     PetscViewerASCIIPrintf(viewer, "Line %D>\n", i);
555:     for (j = 0; j < nopts; j++) {
556:       PetscViewerASCIIPrintf(viewer, "  X: %g Y: %g\n", (double)lg->x[j*dim+i], (double)lg->y[j*dim+i]);
557:     }
558:   }
559:   return(0);
560: }