Actual source code: lg.c

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

 8:  #include petsc.h

 10: PetscCookie DRAWLG_COOKIE = 0;

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

 24: #define CHUNCKSIZE 100

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

 31:     Collective over PetscDraw

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

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

 40:     Level: intermediate

 42:     Concepts: line graph^creating

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

 56:   PetscTypeCompare(obj,PETSC_DRAW_NULL,&isnull);
 57:   if (isnull) {
 58:     PetscDrawOpenNull(obj->comm,(PetscDraw*)outctx);
 59:     return(0);
 60:   }
 61:   PetscHeaderCreate(lg,_p_DrawLG,int,DRAWLG_COOKIE,0,"PetscDrawLG",obj->comm,PetscDrawLGDestroy,0);
 62:   lg->view    = 0;
 63:   lg->destroy = 0;
 64:   lg->nopts   = 0;
 65:   lg->win     = draw;
 66:   lg->dim     = dim;
 67:   lg->xmin    = 1.e20;
 68:   lg->ymin    = 1.e20;
 69:   lg->xmax    = -1.e20;
 70:   lg->ymax    = -1.e20;
 71:   PetscMalloc(2*dim*CHUNCKSIZE*sizeof(PetscReal),&lg->x);
 72:   PetscLogObjectMemory(lg,2*dim*CHUNCKSIZE*sizeof(PetscReal));
 73:   lg->y       = lg->x + dim*CHUNCKSIZE;
 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 && lg->cookie == PETSC_DRAW_COOKIE) return(0);
106:   if (lg->dim == dim) return(0);

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

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

122:    Collective over PetscDrawLG

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

127:    Level: intermediate

129:    Concepts: line graph^restarting

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

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

151:    Collective over PetscDrawLG

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

156:    Level: intermediate

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

165:   if (!lg || lg->cookie != PETSC_DRAW_COOKIE) {
167:   }

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

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

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

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

194:    Level: intermediate

196:    Concepts: line graph^adding points

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

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

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

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

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

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

240:    Input Parameters:
241: .  lg - the linegraph context

243:    Level: intermediate

245:    Concepts: line graph^showing points

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

253:   lg->use_dots = PETSC_TRUE;
254:   return(0);
255: }

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

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

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

271:    Level: intermediate


274:    Concepts: line graph^adding points

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

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

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

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

322: /*@
323:    PetscDrawLGDraw - Redraws a line graph.

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

327:    Input Parameter:
328: .  lg - the line graph context

330:    Level: intermediate

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

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

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

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

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


363:   }
364:   PetscDrawFlush(lg->win);
365:   PetscDrawPause(lg->win);
366:   return(0);
367: }

371: /*@
372:   PetscDrawLGPrint - Prints a line graph.

374:   Not collective

376:   Input Parameter:
377: . lg - the line graph context

379:   Level: beginner

381:   Contributed by Matthew Knepley

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

391:   if (lg && lg->cookie == PETSC_DRAW_COOKIE) return(0);
393:   if (nopts < 1)                  return(0);
394:   if (xmin > xmax || ymin > ymax) return(0);

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

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

414:    Input Parameters:
415: +  xlg - the line graph context
416: -  x_min,x_max,y_min,y_max - the limits

418:    Level: intermediate

420:    Concepts: line graph^setting axis

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

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

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

448:    Output Parameter:
449: .  axis - the axis context

451:    Level: advanced

453: @*/
454: PetscErrorCode PetscDrawLGGetAxis(PetscDrawLG lg,PetscDrawAxis *axis)
455: {
457:   if (lg && lg->cookie == PETSC_DRAW_COOKIE) {
458:     *axis = 0;
459:     return(0);
460:   }
463:   *axis = lg->axis;
464:   return(0);
465: }

469: /*@C
470:    PetscDrawLGGetDraw - Gets the draw context associated with a line graph.

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

474:    Input Parameter:
475: .  lg - the line graph context

477:    Output Parameter:
478: .  draw - the draw context

480:    Level: intermediate

482: @*/
483: PetscErrorCode PetscDrawLGGetDraw(PetscDrawLG lg,PetscDraw *draw)
484: {
488:   if (lg->cookie == PETSC_DRAW_COOKIE) {
489:     *draw = (PetscDraw)lg;
490:   } else {
492:     *draw = lg->win;
493:   }
494:   return(0);
495: }


500: /*@
501:    PetscDrawLGSPDraw - Redraws a line graph.

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

505:    Input Parameter:
506: .  lg - the line graph context

508:    Level: intermediate

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

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

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

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

528:   xmin = PetscMin(lg->xmin,sp->xmin);
529:   ymin = PetscMin(lg->ymin,sp->ymin);
530:   xmax = PetscMax(lg->xmax,sp->xmax);
531:   ymax = PetscMax(lg->ymax,sp->ymax);

533:   PetscDrawClear(draw);
534:   PetscDrawAxisSetLimits(lg->axis,xmin,xmax,ymin,ymax);
535:   PetscDrawAxisDraw(lg->axis);

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

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