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

 23: #define CHUNCKSIZE 100

 25: /*@C
 26:     PetscDrawLGCreate - Creates a line graph data structure.

 28:     Collective over PetscDraw

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

 34:     Output Parameters:
 35: .   outctx - the line graph context

 37:     Level: intermediate

 39:     Concepts: line graph^creating

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

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

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

 83:    Collective over PetscDrawLG

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

 89:    Level: intermediate

 91:    Concepts: line graph^setting number of lines

 93: @*/
 94: int PetscDrawLGSetDimension(PetscDrawLG lg,int dim)
 95: {

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

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

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

115:    Collective over PetscDrawLG

117:    Input Parameter:
118: .  lg - the line graph context.

120:    Level: intermediate

122:    Concepts: line graph^restarting

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

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

142:    Collective over PetscDrawLG

144:    Input Parameter:
145: .  lg - the line graph context

147:    Level: intermediate

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

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

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

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

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

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

183:    Level: intermediate

185:    Concepts: line graph^adding points

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

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

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

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

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

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

226:    Input Parameters:
227: .  lg - the linegraph context

229:    Level: intermediate

231:    Concepts: line graph^showing points

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

239:   lg->use_dots = PETSC_TRUE;
240:   return(0);
241: }

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

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

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

255:    Level: intermediate


258:    Concepts: line graph^adding points

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

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

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

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

303: /*@
304:    PetscDrawLGDraw - Redraws a line graph.

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

308:    Input Parameter:
309: .  lg - the line graph context

311:    Level: intermediate

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

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

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

328:   MPI_Comm_rank(lg->comm,&rank);
329:   if (!rank) {
330: 
331:     for (i=0; i<dim; i++) {
332:       for (j=1; j<nopts; j++) {
333:         PetscDrawLine(draw,lg->x[(j-1)*dim+i],lg->y[(j-1)*dim+i],
334:                         lg->x[j*dim+i],lg->y[j*dim+i],PETSC_DRAW_BLACK+i);
335:         if (lg->use_dots) {
336:           PetscDrawString(draw,lg->x[j*dim+i],lg->y[j*dim+i],PETSC_DRAW_RED,"x");
337:         }
338:       }
339:     }
340:   }
341:   PetscDrawFlush(lg->win);
342:   PetscDrawPause(lg->win);
343:   return(0);
344: }
345: 
346: /*@
347:    PetscDrawLGSetLimits - Sets the axis limits for a line graph. If more
348:    points are added after this call, the limits will be adjusted to
349:    include those additional points.

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

353:    Input Parameters:
354: +  xlg - the line graph context
355: -  x_min,x_max,y_min,y_max - the limits

357:    Level: intermediate

359:    Concepts: line graph^setting axis

361: @*/
362: int PetscDrawLGSetLimits(PetscDrawLG lg,PetscReal x_min,PetscReal x_max,PetscReal y_min,PetscReal y_max)
363: {
365:   if (lg && lg->cookie == PETSC_DRAW_COOKIE) return(0);
367:   (lg)->xmin = x_min;
368:   (lg)->xmax = x_max;
369:   (lg)->ymin = y_min;
370:   (lg)->ymax = y_max;
371:   return(0);
372: }
373: 
374: /*@C
375:    PetscDrawLGGetAxis - Gets the axis context associated with a line graph.
376:    This is useful if one wants to change some axis property, such as
377:    labels, color, etc. The axis context should not be destroyed by the
378:    application code.

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

382:    Input Parameter:
383: .  lg - the line graph context

385:    Output Parameter:
386: .  axis - the axis context

388:    Level: advanced

390: @*/
391: int PetscDrawLGGetAxis(PetscDrawLG lg,PetscDrawAxis *axis)
392: {
394:   if (lg && lg->cookie == PETSC_DRAW_COOKIE) {
395:     *axis = 0;
396:     return(0);
397:   }
399:   *axis = lg->axis;
400:   return(0);
401: }

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

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

408:    Input Parameter:
409: .  lg - the line graph context

411:    Output Parameter:
412: .  draw - the draw context

414:    Level: intermediate

416: @*/
417: int PetscDrawLGGetDraw(PetscDrawLG lg,PetscDraw *draw)
418: {
421:   if (lg->cookie == PETSC_DRAW_COOKIE) {
422:     *draw = (PetscDraw)lg;
423:   } else {
425:     *draw = lg->win;
426:   }
427:   return(0);
428: }