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