Actual source code: lg.c

  1: /*$Id: lg.c,v 1.76 2001/04/10 19:34:23 bsmith Exp $*/
  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 petsc.h

 11: int DRAWLG_COOKIE;

 13: struct _p_DrawLG {
 14:   PETSCHEADER(int)
 15:   int           (*destroy)(PetscDrawLG);
 16:   int           (*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

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

 30:     Collective over PetscDraw

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

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

 39:     Level: intermediate

 41:     Concepts: line graph^creating

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

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

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

 85:    Collective over PetscDrawLG

 87:    Input Parameter:
 88: +  lg - the line graph context.
 89: -  dim - the number of curves.

 91:    Level: intermediate

 93:    Concepts: line graph^setting number of lines

 95: @*/
 96: int PetscDrawLGSetDimension(PetscDrawLG lg,int dim)
 97: {

101:   if (lg && lg->cookie == PETSC_DRAW_COOKIE) return(0);
103:   if (lg->dim == dim) return(0);

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

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

117:    Collective over PetscDrawLG

119:    Input Parameter:
120: .  lg - the line graph context.

122:    Level: intermediate

124:    Concepts: line graph^restarting

126: @*/
127: int PetscDrawLGReset(PetscDrawLG lg)
128: {
130:   if (lg && lg->cookie == PETSC_DRAW_COOKIE) return(0);
132:   lg->xmin  = 1.e20;
133:   lg->ymin  = 1.e20;
134:   lg->xmax  = -1.e20;
135:   lg->ymax  = -1.e20;
136:   lg->loc   = 0;
137:   lg->nopts = 0;
138:   return(0);
139: }

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

144:    Collective over PetscDrawLG

146:    Input Parameter:
147: .  lg - the line graph context

149:    Level: intermediate

151: .seealso:  PetscDrawLGCreate()
152: @*/
153: int PetscDrawLGDestroy(PetscDrawLG lg)
154: {

158:   if (!lg || lg->cookie != PETSC_DRAW_COOKIE) {
160:   }

162:   if (--lg->refct > 0) return(0);
163:   if (lg && lg->cookie == PETSC_DRAW_COOKIE) {
164:     PetscObjectDestroy((PetscObject)lg);
165:     return(0);
166:   }
167:   PetscDrawAxisDestroy(lg->axis);
168:   PetscFree(lg->x);
169:   PetscLogObjectDestroy(lg);
170:   PetscHeaderDestroy(lg);
171:   return(0);
172: }

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

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

180:    Input Parameters:
181: +  lg - the LineGraph data structure
182: -  x, y - the points to two vectors containing the new x and y 
183:           point for each curve.

185:    Level: intermediate

187:    Concepts: line graph^adding points

189: .seealso: PetscDrawLGAddPoints()
190: @*/
191: int PetscDrawLGAddPoint(PetscDrawLG lg,PetscReal *x,PetscReal *y)
192: {
193:   int i,ierr;

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

199:   if (lg->loc+lg->dim >= lg->len) { /* allocate more space */
200:     PetscReal *tmpx,*tmpy;
201:     PetscMalloc((2*lg->len+2*lg->dim*CHUNCKSIZE)*sizeof(PetscReal),&tmpx);
202:     PetscLogObjectMemory(lg,2*lg->dim*CHUNCKSIZE*sizeof(PetscReal));
203:     tmpy = tmpx + lg->len + lg->dim*CHUNCKSIZE;
204:     PetscMemcpy(tmpx,lg->x,lg->len*sizeof(PetscReal));
205:     PetscMemcpy(tmpy,lg->y,lg->len*sizeof(PetscReal));
206:     PetscFree(lg->x);
207:     lg->x = tmpx; lg->y = tmpy;
208:     lg->len += lg->dim*CHUNCKSIZE;
209:   }
210:   for (i=0; i<lg->dim; i++) {
211:     if (x[i] > lg->xmax) lg->xmax = x[i];
212:     if (x[i] < lg->xmin) lg->xmin = x[i];
213:     if (y[i] > lg->ymax) lg->ymax = y[i];
214:     if (y[i] < lg->ymin) lg->ymin = y[i];

216:     lg->x[lg->loc]   = x[i];
217:     lg->y[lg->loc++] = y[i];
218:   }
219:   lg->nopts++;
220:   return(0);
221: }

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

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

228:    Input Parameters:
229: .  lg - the linegraph context

231:    Level: intermediate

233:    Concepts: line graph^showing points

235: @*/
236: int PetscDrawLGIndicateDataPoints(PetscDrawLG lg)
237: {
239:   if (lg && lg->cookie == PETSC_DRAW_COOKIE) return(0);

241:   lg->use_dots = PETSC_TRUE;
242:   return(0);
243: }

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

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

251:    Input Parameters:
252: +  lg - the LineGraph data structure
253: .  xx,yy - points to two arrays of pointers that point to arrays 
254:            containing the new x and y points for each curve.
255: -  n - number of points being added

257:    Level: intermediate


260:    Concepts: line graph^adding points

262: .seealso: PetscDrawLGAddPoint()
263: @*/
264: int PetscDrawLGAddPoints(PetscDrawLG lg,int n,PetscReal **xx,PetscReal **yy)
265: {
266:   int       i,j,k,ierr;
267:   PetscReal *x,*y;

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

276:     if (n > chunk) chunk = n;
277:     PetscMalloc((2*lg->len+2*lg->dim*chunk)*sizeof(PetscReal),&tmpx);
278:     PetscLogObjectMemory(lg,2*lg->dim*chunk*sizeof(PetscReal));
279:     tmpy = tmpx + lg->len + lg->dim*chunk;
280:     PetscMemcpy(tmpx,lg->x,lg->len*sizeof(PetscReal));
281:     PetscMemcpy(tmpy,lg->y,lg->len*sizeof(PetscReal));
282:     PetscFree(lg->x);
283:     lg->x    = tmpx; lg->y = tmpy;
284:     lg->len += lg->dim*chunk;
285:   }
286:   for (j=0; j<lg->dim; j++) {
287:     x = xx[j]; y = yy[j];
288:     k = lg->loc + j;
289:     for (i=0; i<n; i++) {
290:       if (x[i] > lg->xmax) lg->xmax = x[i];
291:       if (x[i] < lg->xmin) lg->xmin = x[i];
292:       if (y[i] > lg->ymax) lg->ymax = y[i];
293:       if (y[i] < lg->ymin) lg->ymin = y[i];

295:       lg->x[k]   = x[i];
296:       lg->y[k] = y[i];
297:       k += lg->dim;
298:     }
299:   }
300:   lg->loc   += n*lg->dim;
301:   lg->nopts += n;
302:   return(0);
303: }

305: /*@
306:    PetscDrawLGDraw - Redraws a line graph.

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

310:    Input Parameter:
311: .  lg - the line graph context

313:    Level: intermediate

315: @*/
316: int PetscDrawLGDraw(PetscDrawLG lg)
317: {
318:   PetscReal xmin=lg->xmin,xmax=lg->xmax,ymin=lg->ymin,ymax=lg->ymax;
319:   int       i,j,dim = lg->dim,nopts = lg->nopts,rank,ierr;
320:   PetscDraw draw = lg->win;

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

326:   PetscDrawClear(draw);
327:   PetscDrawAxisSetLimits(lg->axis,xmin,xmax,ymin,ymax);
328:   PetscDrawAxisDraw(lg->axis);

330:   MPI_Comm_rank(lg->comm,&rank);
331:   if (!rank) {
332: 
333:     for (i=0; i<dim; i++) {
334:       for (j=1; j<nopts; j++) {
335:         PetscDrawLine(draw,lg->x[(j-1)*dim+i],lg->y[(j-1)*dim+i],
336:                         lg->x[j*dim+i],lg->y[j*dim+i],PETSC_DRAW_BLACK+i);
337:         if (lg->use_dots) {
338:           PetscDrawString(draw,lg->x[j*dim+i],lg->y[j*dim+i],PETSC_DRAW_RED,"x");
339:         }
340:       }
341:     }
342:   }
343:   PetscDrawFlush(lg->win);
344:   PetscDrawPause(lg->win);
345:   return(0);
346: }

348: /*@
349:   PetscDrawLGPrint - Prints a line graph.

351:   Not collective

353:   Input Parameter:
354: . lg - the line graph context

356:   Level: beginner

358:   Contributed by Matthew Knepley

360: .keywords:  draw, line, graph
361: @*/
362: int PetscDrawLGPrint(PetscDrawLG lg)
363: {
364:   PetscReal xmin=lg->xmin, xmax=lg->xmax, ymin=lg->ymin, ymax=lg->ymax;
365:   int       i, j, dim = lg->dim, nopts = lg->nopts;

368:   if (lg && lg->cookie == PETSC_DRAW_COOKIE) return(0);
370:   if (nopts < 1)                  return(0);
371:   if (xmin > xmax || ymin > ymax) return(0);

373:   for(i = 0; i < dim; i++) {
374:     PetscPrintf(lg->comm, "Line %dn", i);
375:     for(j = 0; j < nopts; j++) {
376:       PetscPrintf(lg->comm, "  X: %g Y: %gn", lg->x[j*dim+i], lg->y[j*dim+i]);
377:     }
378:   }
379:   return(0);
380: }
381: 
382: /*@
383:    PetscDrawLGSetLimits - Sets the axis limits for a line graph. If more
384:    points are added after this call, the limits will be adjusted to
385:    include those additional points.

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

389:    Input Parameters:
390: +  xlg - the line graph context
391: -  x_min,x_max,y_min,y_max - the limits

393:    Level: intermediate

395:    Concepts: line graph^setting axis

397: @*/
398: int PetscDrawLGSetLimits(PetscDrawLG lg,PetscReal x_min,PetscReal x_max,PetscReal y_min,PetscReal y_max)
399: {
401:   if (lg && lg->cookie == PETSC_DRAW_COOKIE) return(0);
403:   (lg)->xmin = x_min;
404:   (lg)->xmax = x_max;
405:   (lg)->ymin = y_min;
406:   (lg)->ymax = y_max;
407:   return(0);
408: }
409: 
410: /*@C
411:    PetscDrawLGGetAxis - Gets the axis context associated with a line graph.
412:    This is useful if one wants to change some axis property, such as
413:    labels, color, etc. The axis context should not be destroyed by the
414:    application code.

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

418:    Input Parameter:
419: .  lg - the line graph context

421:    Output Parameter:
422: .  axis - the axis context

424:    Level: advanced

426: @*/
427: int PetscDrawLGGetAxis(PetscDrawLG lg,PetscDrawAxis *axis)
428: {
430:   if (lg && lg->cookie == PETSC_DRAW_COOKIE) {
431:     *axis = 0;
432:     return(0);
433:   }
435:   *axis = lg->axis;
436:   return(0);
437: }

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

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

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

447:    Output Parameter:
448: .  draw - the draw context

450:    Level: intermediate

452: @*/
453: int PetscDrawLGGetDraw(PetscDrawLG lg,PetscDraw *draw)
454: {
457:   if (lg->cookie == PETSC_DRAW_COOKIE) {
458:     *draw = (PetscDraw)lg;
459:   } else {
461:     *draw = lg->win;
462:   }
463:   return(0);
464: }