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" /*I "petsc.h" I*/
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: }