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: }