Actual source code: lg.c

  1: #define PETSC_DLL
  2: /*
  3:        Contains the data structure for plotting several line
  4:     graphs in a window with an axis. This is intended for line 
  5:     graphs that change dynamically by adding more points onto 
  6:     the end of the X axis.
  7: */

 9:  #include petscsys.h

 11: PetscCookie DRAWLG_COOKIE = 0;

 13: struct _p_DrawLG {
 14:   PETSCHEADER(int);
 15:   PetscErrorCode (*destroy)(PetscDrawLG);
 16:   PetscErrorCode (*view)(PetscDrawLG,PetscViewer);
 17:   int           len,loc;
 18:   PetscDraw     win;
 19:   PetscDrawAxis axis;
 20:   PetscReal     xmin,xmax,ymin,ymax,*x,*y;
 21:   int           nopts,dim;
 22:   PetscTruth    use_dots;
 23: };

 25: #define CHUNCKSIZE 100

 29: /*@
 30:     PetscDrawLGCreate - Creates a line graph data structure.

 32:     Collective over PetscDraw

 34:     Input Parameters:
 35: +   draw - the window where the graph will be made.
 36: -   dim - the number of curves which will be drawn

 38:     Output Parameters:
 39: .   outctx - the line graph context

 41:     Level: intermediate

 43:     Concepts: line graph^creating

 45: .seealso:  PetscDrawLGDestroy()
 46: @*/
 47: PetscErrorCode  PetscDrawLGCreate(PetscDraw draw,int dim,PetscDrawLG *outctx)
 48: {
 50:   PetscTruth     isnull;
 51:   PetscObject    obj = (PetscObject)draw;
 52:   PetscDrawLG    lg;

 57:   PetscTypeCompare(obj,PETSC_DRAW_NULL,&isnull);
 58:   if (isnull) {
 59:     PetscDrawOpenNull(((PetscObject)obj)->comm,(PetscDraw*)outctx);
 60:     return(0);
 61:   }
 62:   PetscHeaderCreate(lg,_p_DrawLG,int,DRAWLG_COOKIE,0,"PetscDrawLG",((PetscObject)obj)->comm,PetscDrawLGDestroy,0);
 63:   lg->view    = 0;
 64:   lg->destroy = 0;
 65:   lg->nopts   = 0;
 66:   lg->win     = draw;
 67:   lg->dim     = dim;
 68:   lg->xmin    = 1.e20;
 69:   lg->ymin    = 1.e20;
 70:   lg->xmax    = -1.e20;
 71:   lg->ymax    = -1.e20;
 72:   PetscMalloc2(dim*CHUNCKSIZE,PetscReal,&lg->x,dim*CHUNCKSIZE,PetscReal,&lg->y);
 73:   PetscLogObjectMemory(lg,2*dim*CHUNCKSIZE*sizeof(PetscReal));
 74:   lg->len     = dim*CHUNCKSIZE;
 75:   lg->loc     = 0;
 76:   lg->use_dots= PETSC_FALSE;
 77:   PetscDrawAxisCreate(draw,&lg->axis);
 78:   PetscLogObjectParent(lg,lg->axis);
 79:   *outctx = lg;
 80:   return(0);
 81: }

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

 88:    Collective over PetscDrawLG

 90:    Input Parameter:
 91: +  lg - the line graph context.
 92: -  dim - the number of curves.

 94:    Level: intermediate

 96:    Concepts: line graph^setting number of lines

 98: @*/
 99: PetscErrorCode  PetscDrawLGSetDimension(PetscDrawLG lg,int dim)
100: {

104:   if (lg && ((PetscObject)lg)->cookie == PETSC_DRAW_COOKIE) return(0);
106:   if (lg->dim == dim) return(0);

108:   PetscFree2(lg->x,lg->y);
109:   lg->dim = dim;
110:   PetscMalloc2(dim*CHUNCKSIZE,PetscReal,&lg->x,dim*CHUNCKSIZE,PetscReal,&lg->y);
111:   PetscLogObjectMemory(lg,2*dim*CHUNCKSIZE*sizeof(PetscReal));
112:   lg->len     = dim*CHUNCKSIZE;
113:   return(0);
114: }

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

121:    Collective over PetscDrawLG

123:    Input Parameter:
124: .  lg - the line graph context.

126:    Level: intermediate

128:    Concepts: line graph^restarting

130: @*/
131: PetscErrorCode  PetscDrawLGReset(PetscDrawLG lg)
132: {
134:   if (lg && ((PetscObject)lg)->cookie == PETSC_DRAW_COOKIE) return(0);
136:   lg->xmin  = 1.e20;
137:   lg->ymin  = 1.e20;
138:   lg->xmax  = -1.e20;
139:   lg->ymax  = -1.e20;
140:   lg->loc   = 0;
141:   lg->nopts = 0;
142:   return(0);
143: }

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

150:    Collective over PetscDrawLG

152:    Input Parameter:
153: .  lg - the line graph context

155:    Level: intermediate

157: .seealso:  PetscDrawLGCreate()
158: @*/
159: PetscErrorCode  PetscDrawLGDestroy(PetscDrawLG lg)
160: {

164:   if (!lg || ((PetscObject)lg)->cookie != PETSC_DRAW_COOKIE) {
166:   }

168:   if (--((PetscObject)lg)->refct > 0) return(0);
169:   if (lg && ((PetscObject)lg)->cookie == PETSC_DRAW_COOKIE) {
170:     PetscObjectDestroy((PetscObject)lg);
171:     return(0);
172:   }
173:   PetscDrawAxisDestroy(lg->axis);
174:   PetscFree2(lg->x,lg->y);
175:   PetscHeaderDestroy(lg);
176:   return(0);
177: }

181: /*@
182:    PetscDrawLGAddPoint - Adds another point to each of the line graphs. 
183:    The new point must have an X coordinate larger than the old points.

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

187:    Input Parameters:
188: +  lg - the LineGraph data structure
189: -  x, y - the points to two vectors containing the new x and y 
190:           point for each curve.

192:    Level: intermediate

194:    Concepts: line graph^adding points

196: .seealso: PetscDrawLGAddPoints()
197: @*/
198: PetscErrorCode  PetscDrawLGAddPoint(PetscDrawLG lg,PetscReal *x,PetscReal *y)
199: {
201:   int            i;

204:   if (lg && ((PetscObject)lg)->cookie == PETSC_DRAW_COOKIE) return(0);

207:   if (lg->loc+lg->dim >= lg->len) { /* allocate more space */
208:     PetscReal *tmpx,*tmpy;
209:     PetscMalloc2(lg->len+lg->dim*CHUNCKSIZE,PetscReal,&tmpx,lg->len+lg->dim*CHUNCKSIZE,PetscReal,&tmpy);
210:     PetscLogObjectMemory(lg,2*lg->dim*CHUNCKSIZE*sizeof(PetscReal));
211:     PetscMemcpy(tmpx,lg->x,lg->len*sizeof(PetscReal));
212:     PetscMemcpy(tmpy,lg->y,lg->len*sizeof(PetscReal));
213:     PetscFree2(lg->x,lg->y);
214:     lg->x = tmpx;
215:     lg->y = tmpy;
216:     lg->len += lg->dim*CHUNCKSIZE;
217:   }
218:   for (i=0; i<lg->dim; i++) {
219:     if (x[i] > lg->xmax) lg->xmax = x[i];
220:     if (x[i] < lg->xmin) lg->xmin = x[i];
221:     if (y[i] > lg->ymax) lg->ymax = y[i];
222:     if (y[i] < lg->ymin) lg->ymin = y[i];

224:     lg->x[lg->loc]   = x[i];
225:     lg->y[lg->loc++] = y[i];
226:   }
227:   lg->nopts++;
228:   return(0);
229: }

233: /*@
234:    PetscDrawLGIndicateDataPoints - Causes LG to draw a big dot for each data-point.

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

238:    Input Parameters:
239: .  lg - the linegraph context

241:    Level: intermediate

243:    Concepts: line graph^showing points

245: @*/
246: PetscErrorCode  PetscDrawLGIndicateDataPoints(PetscDrawLG lg)
247: {
249:   if (lg && ((PetscObject)lg)->cookie == PETSC_DRAW_COOKIE) return(0);

251:   lg->use_dots = PETSC_TRUE;
252:   return(0);
253: }

257: /*@C
258:    PetscDrawLGAddPoints - Adds several points to each of the line graphs.
259:    The new points must have an X coordinate larger than the old points.

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

263:    Input Parameters:
264: +  lg - the LineGraph data structure
265: .  xx,yy - points to two arrays of pointers that point to arrays 
266:            containing the new x and y points for each curve.
267: -  n - number of points being added

269:    Level: intermediate


272:    Concepts: line graph^adding points

274: .seealso: PetscDrawLGAddPoint()
275: @*/
276: PetscErrorCode  PetscDrawLGAddPoints(PetscDrawLG lg,int n,PetscReal **xx,PetscReal **yy)
277: {
279:   int            i,j,k;
280:   PetscReal      *x,*y;

283:   if (lg && ((PetscObject)lg)->cookie == PETSC_DRAW_COOKIE) return(0);
285:   if (lg->loc+n*lg->dim >= lg->len) { /* allocate more space */
286:     PetscReal *tmpx,*tmpy;
287:     int    chunk = CHUNCKSIZE;

289:     if (n > chunk) chunk = n;
290:     PetscMalloc2(lg->len+lg->dim*chunk,PetscReal,&tmpx,lg->len+lg->dim*chunk,PetscReal,&tmpy);
291:     PetscLogObjectMemory(lg,2*lg->dim*chunk*sizeof(PetscReal));
292:     PetscMemcpy(tmpx,lg->x,lg->len*sizeof(PetscReal));
293:     PetscMemcpy(tmpy,lg->y,lg->len*sizeof(PetscReal));
294:     PetscFree2(lg->x,lg->y);
295:     lg->x = tmpx;
296:     lg->y = tmpy;
297:     lg->len += lg->dim*chunk;
298:   }
299:   for (j=0; j<lg->dim; j++) {
300:     x = xx[j]; y = yy[j];
301:     k = lg->loc + j;
302:     for (i=0; i<n; i++) {
303:       if (x[i] > lg->xmax) lg->xmax = x[i];
304:       if (x[i] < lg->xmin) lg->xmin = x[i];
305:       if (y[i] > lg->ymax) lg->ymax = y[i];
306:       if (y[i] < lg->ymin) lg->ymin = y[i];

308:       lg->x[k]   = x[i];
309:       lg->y[k] = y[i];
310:       k += lg->dim;
311:     }
312:   }
313:   lg->loc   += n*lg->dim;
314:   lg->nopts += n;
315:   return(0);
316: }

320: /*@
321:    PetscDrawLGDraw - Redraws a line graph.

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

325:    Input Parameter:
326: .  lg - the line graph context

328:    Level: intermediate

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

332: @*/
333: PetscErrorCode  PetscDrawLGDraw(PetscDrawLG lg)
334: {
335:   PetscReal      xmin=lg->xmin,xmax=lg->xmax,ymin=lg->ymin,ymax=lg->ymax;
337:   int            i,j,dim = lg->dim,nopts = lg->nopts,rank;
338:   PetscDraw      draw = lg->win;

341:   if (lg && ((PetscObject)lg)->cookie == PETSC_DRAW_COOKIE) return(0);

344:   PetscDrawClear(draw);
345:   PetscDrawAxisSetLimits(lg->axis,xmin,xmax,ymin,ymax);
346:   PetscDrawAxisDraw(lg->axis);

348:   MPI_Comm_rank(((PetscObject)lg)->comm,&rank);
349:   if (!rank) {
350: 
351:     for (i=0; i<dim; i++) {
352:       for (j=1; j<nopts; j++) {
353:         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);
354:         if (lg->use_dots) {
355:           PetscDrawString(draw,lg->x[j*dim+i],lg->y[j*dim+i],PETSC_DRAW_RED,"x");
356:         }
357:       }
358:     }
359:   }
360:   PetscDrawFlush(lg->win);
361:   PetscDrawPause(lg->win);
362:   return(0);
363: }

367: /*@
368:   PetscDrawLGPrint - Prints a line graph.

370:   Not collective

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

375:   Level: beginner

377:   Contributed by Matthew Knepley

379: .keywords:  draw, line, graph
380: @*/
381: PetscErrorCode  PetscDrawLGPrint(PetscDrawLG lg)
382: {
383:   PetscReal xmin=lg->xmin, xmax=lg->xmax, ymin=lg->ymin, ymax=lg->ymax;
384:   int       i, j, dim = lg->dim, nopts = lg->nopts;

387:   if (lg && ((PetscObject)lg)->cookie == PETSC_DRAW_COOKIE) return(0);
389:   if (nopts < 1)                  return(0);
390:   if (xmin > xmax || ymin > ymax) return(0);

392:   for(i = 0; i < dim; i++) {
393:     PetscPrintf(((PetscObject)lg)->comm, "Line %d>\n", i);
394:     for(j = 0; j < nopts; j++) {
395:       PetscPrintf(((PetscObject)lg)->comm, "  X: %G Y: %G\n", lg->x[j*dim+i], lg->y[j*dim+i]);
396:     }
397:   }
398:   return(0);
399: }
400: 
403: /*@
404:    PetscDrawLGSetLimits - Sets the axis limits for a line graph. If more
405:    points are added after this call, the limits will be adjusted to
406:    include those additional points.

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

410:    Input Parameters:
411: +  xlg - the line graph context
412: -  x_min,x_max,y_min,y_max - the limits

414:    Level: intermediate

416:    Concepts: line graph^setting axis

418: @*/
419: PetscErrorCode  PetscDrawLGSetLimits(PetscDrawLG lg,PetscReal x_min,PetscReal x_max,PetscReal y_min,PetscReal y_max)
420: {
422:   if (lg && ((PetscObject)lg)->cookie == PETSC_DRAW_COOKIE) return(0);
424:   (lg)->xmin = x_min;
425:   (lg)->xmax = x_max;
426:   (lg)->ymin = y_min;
427:   (lg)->ymax = y_max;
428:   return(0);
429: }
430: 
433: /*@
434:    PetscDrawLGGetAxis - Gets the axis context associated with a line graph.
435:    This is useful if one wants to change some axis property, such as
436:    labels, color, etc. The axis context should not be destroyed by the
437:    application code.

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

441:    Input Parameter:
442: .  lg - the line graph context

444:    Output Parameter:
445: .  axis - the axis context

447:    Level: advanced

449: @*/
450: PetscErrorCode  PetscDrawLGGetAxis(PetscDrawLG lg,PetscDrawAxis *axis)
451: {
453:   if (lg && ((PetscObject)lg)->cookie == PETSC_DRAW_COOKIE) {
454:     *axis = 0;
455:     return(0);
456:   }
459:   *axis = lg->axis;
460:   return(0);
461: }

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

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

470:    Input Parameter:
471: .  lg - the line graph context

473:    Output Parameter:
474: .  draw - the draw context

476:    Level: intermediate

478: @*/
479: PetscErrorCode  PetscDrawLGGetDraw(PetscDrawLG lg,PetscDraw *draw)
480: {
484:   if (((PetscObject)lg)->cookie == PETSC_DRAW_COOKIE) {
485:     *draw = (PetscDraw)lg;
486:   } else {
488:     *draw = lg->win;
489:   }
490:   return(0);
491: }


496: /*@
497:    PetscDrawLGSPDraw - Redraws a line graph.

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

501:    Input Parameter:
502: .  lg - the line graph context

504:    Level: intermediate

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

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

510: @*/
511: PetscErrorCode  PetscDrawLGSPDraw(PetscDrawLG lg,PetscDrawSP spin)
512: {
513:   PetscDrawLG    sp = (PetscDrawLG)spin;
514:   PetscReal      xmin,xmax,ymin,ymax;
516:   int            i,j,dim,nopts,rank;
517:   PetscDraw      draw = lg->win;

520:   if (lg && ((PetscObject)lg)->cookie == PETSC_DRAW_COOKIE) return(0);

524:   xmin = PetscMin(lg->xmin,sp->xmin);
525:   ymin = PetscMin(lg->ymin,sp->ymin);
526:   xmax = PetscMax(lg->xmax,sp->xmax);
527:   ymax = PetscMax(lg->ymax,sp->ymax);

529:   PetscDrawClear(draw);
530:   PetscDrawAxisSetLimits(lg->axis,xmin,xmax,ymin,ymax);
531:   PetscDrawAxisDraw(lg->axis);

533:   MPI_Comm_rank(((PetscObject)lg)->comm,&rank);
534:   if (!rank) {
535: 
536:     dim   = lg->dim;
537:     nopts = lg->nopts;
538:     for (i=0; i<dim; i++) {
539:       for (j=1; j<nopts; j++) {
540:         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);
541:         if (lg->use_dots) {
542:           PetscDrawString(draw,lg->x[j*dim+i],lg->y[j*dim+i],PETSC_DRAW_RED,"x");
543:         }
544:       }
545:     }

547:     dim   = sp->dim;
548:     nopts = sp->nopts;
549:     for (i=0; i<dim; i++) {
550:       for (j=0; j<nopts; j++) {
551:         PetscDrawString(draw,sp->x[j*dim+i],sp->y[j*dim+i],PETSC_DRAW_RED,"x");
552:       }
553:     }
554:   }
555:   PetscDrawFlush(lg->win);
556:   PetscDrawPause(lg->win);
557:   return(0);
558: }