Actual source code: lgc.c

petsc-3.6.1 2015-08-06
Report Typos and Errors
  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_markers) {
116:           PetscDrawMarker(draw,lg->x[j*dim+i],lg->y[j*dim+i],PETSC_DRAW_RED);
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:         PetscDrawMarker(draw,sp->x[j*dim+i],sp->y[j*dim+i],PETSC_DRAW_RED);
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,PETSC_DRAWLG_CLASSID,"PetscDrawLG","Line graph","Draw",PetscObjectComm((PetscObject)obj),PetscDrawLGDestroy,NULL);

172:   lg->view    = NULL;
173:   lg->destroy = NULL;
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,&lg->x,dim*CHUNCKSIZE,&lg->y);
183:   PetscLogObjectMemory((PetscObject)lg,2*dim*CHUNCKSIZE*sizeof(PetscReal));

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

189:   PetscDrawAxisCreate(draw,&lg->axis);
190:   PetscLogObjectParent((PetscObject)lg,(PetscObject)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:   PetscMalloc1(lg->dim,&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:     PetscMalloc1(lg->dim,&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,&lg->x,dim*CHUNCKSIZE,&lg->y);
330:   PetscLogObjectMemory((PetscObject)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:    PetscDrawLGSetUseMarkers - Causes LG to draw a marker 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
413: -  flg - should mark each data point

415:    Options Database:
416: .  -lg_use_markers  <true,false>

418:    Level: intermediate

420:    Concepts: line graph^showing points

422: @*/
423: PetscErrorCode  PetscDrawLGSetUseMarkers(PetscDrawLG lg,PetscBool flg)
424: {
426:   if (lg && ((PetscObject)lg)->classid == PETSC_DRAW_CLASSID) return(0);

428:   lg->use_markers = flg;
429:   return(0);
430: }

432: #if defined(PETSC_HAVE_SETJMP_H) && defined(PETSC_HAVE_X)
433: #include <X11/Xlib.h>
434: #include <X11/Xutil.h>
435: #include <setjmp.h>
436: static jmp_buf PetscXIOErrorJumpBuf;
437: static void PetscXIOHandler(Display *dpy)
438: {
439:   longjmp(PetscXIOErrorJumpBuf, 1);
440: }
441: #endif

445: /*@
446:    PetscDrawLGDraw - Redraws a line graph.

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

450:    Input Parameter:
451: .  lg - the line graph context

453:    Level: intermediate

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

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

467:   if (lg && ((PetscObject)lg)->classid == PETSC_DRAW_CLASSID) return(0);
469:   PetscDrawIsNull(lg->win,&isnull);
470:   if (isnull) return(0);

472: #if defined(PETSC_HAVE_SETJMP_H) && defined(PETSC_HAVE_X)
473:   if (!setjmp(PetscXIOErrorJumpBuf)) XSetIOErrorHandler((XIOErrorHandler)PetscXIOHandler);
474:   else {
475:     XSetIOErrorHandler(NULL);
476:     PetscDrawSetType(draw,PETSC_DRAW_NULL);
477:     return(0);
478:   }
479: #endif

481:   PetscDrawCheckResizedWindow(draw);
482:   PetscDrawClear(draw);
483:   PetscDrawAxisSetLimits(lg->axis,xmin,xmax,ymin,ymax);
484:   PetscDrawAxisDraw(lg->axis);

486:   MPI_Comm_rank(PetscObjectComm((PetscObject)lg),&rank);
487:   if (!rank) {
488:     for (i=0; i<dim; i++) {
489:       for (j=1; j<nopts; j++) {
490:         if (lg->colors) cl = lg->colors[i];
491:         else cl = PETSC_DRAW_BLACK+i;
492:         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);
493:         if (lg->use_markers) {
494:           PetscDrawMarker(draw,lg->x[j*dim+i],lg->y[j*dim+i],cl);
495:         }
496:       }
497:     }
498:   }
499:   if (!rank && lg->legend) {
500:     PetscReal xl,yl,xr,yr,tw,th;
501:     size_t    len,mlen = 0;
502:     int       cl;
503:     PetscDrawGetCoordinates(draw,&xl,&yl,&xr,&yr);
504:     PetscDrawStringGetSize(draw,&tw,&th);
505:     for (i=0; i<dim; i++) {
506:       PetscStrlen(lg->legend[i],&len);
507:       mlen = PetscMax(mlen,len);
508:     }
509:     PetscDrawLine(draw,xr - (mlen + 8)*tw,yr - 3*th,xr - 2*tw,yr - 3*th,PETSC_DRAW_BLACK);
510:     PetscDrawLine(draw,xr - (mlen + 8)*tw,yr - 3*th,xr - (mlen + 8)*tw,yr - (4+lg->dim)*th,PETSC_DRAW_BLACK);
511:     for  (i=0; i<dim; i++) {
512:       cl   = (lg->colors ? lg->colors[i] : i + 1);
513:       PetscDrawLine(draw,xr - (mlen + 6.7)*tw,yr - (4 + i)*th,xr - (mlen + 3.2)*tw,yr - (4 + i)*th,cl);
514:       PetscDrawString(draw,xr - (mlen + 3)*tw,yr - (4.5 + i)*th,PETSC_DRAW_BLACK,lg->legend[i]);
515:     }
516:     PetscDrawLine(draw,xr - 2*tw,yr - 3*th,xr - 2*tw,yr - (4+lg->dim)*th,PETSC_DRAW_BLACK);
517:     PetscDrawLine(draw,xr - (mlen + 8)*tw,yr - (4+lg->dim)*th,xr - 2*tw,yr - (4+lg->dim)*th,PETSC_DRAW_BLACK);
518:   }
519:   if (!rank) {PetscDrawFlush(lg->win);}
520:   PetscDrawPause(lg->win);
521: #if defined(PETSC_HAVE_SETJMP_H) && defined(PETSC_HAVE_X)
522:   XSetIOErrorHandler(NULL);
523: #endif
524:   return(0);
525: }

529: /*@
530:   PetscDrawLGView - Prints a line graph.

532:   Not collective

534:   Input Parameter:
535: . lg - the line graph context

537:   Level: beginner

539: .keywords:  draw, line, graph
540: @*/
541: PetscErrorCode  PetscDrawLGView(PetscDrawLG lg,PetscViewer viewer)
542: {
543:   PetscReal      xmin=lg->xmin, xmax=lg->xmax, ymin=lg->ymin, ymax=lg->ymax;
544:   PetscInt       i, j, dim = lg->dim, nopts = lg->nopts;

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

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

568: /*@
569:     PetscDrawLGSetFromOptions - Sets options related to the PetscDrawLG

571:     Collective over PetscDrawLG

573:     Options Database:

575:     Level: intermediate

577:     Concepts: line graph^creating

579: .seealso:  PetscDrawLGDestroy(), PetscDrawLGCreate()
580: @*/
581: PetscErrorCode  PetscDrawLGSetFromOptions(PetscDrawLG lg)
582: {
584:   PetscBool      flg=PETSC_FALSE, set;

587:   PetscOptionsGetBool(NULL,"-lg_use_markers",&flg,&set);
588:   if (set) {PetscDrawLGSetUseMarkers(lg,flg);}
589:   return(0);
590: }