Actual source code: lg.c
1: #define PETSC_DLL
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: PetscCookie DRAWLG_COOKIE = 0;
13: struct _p_DrawLG {
14: PETSCHEADER(int);
15: PetscErrorCode (*destroy)(PetscDrawLG);
16: PetscErrorCode (*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
29: /*@
30: PetscDrawLGCreate - Creates a line graph data structure.
32: Collective over PetscDraw
34: Input Parameters:
35: + draw - the window where the graph will be made.
36: - dim - the number of line cures which will be drawn
38: Output Parameters:
39: . outctx - the line graph context
41: Level: intermediate
43: Concepts: line graph^creating
45: .seealso: PetscDrawLGDestroy()
46: @*/
47: PetscErrorCode PetscDrawLGCreate(PetscDraw draw,int dim,PetscDrawLG *outctx)
48: {
50: PetscTruth isnull;
51: PetscObject obj = (PetscObject)draw;
52: PetscDrawLG lg;
57: PetscTypeCompare(obj,PETSC_DRAW_NULL,&isnull);
58: if (isnull) {
59: PetscDrawOpenNull(obj->comm,(PetscDraw*)outctx);
60: return(0);
61: }
62: PetscHeaderCreate(lg,_p_DrawLG,int,DRAWLG_COOKIE,0,"PetscDrawLG",obj->comm,PetscDrawLGDestroy,0);
63: lg->view = 0;
64: lg->destroy = 0;
65: lg->nopts = 0;
66: lg->win = draw;
67: lg->dim = dim;
68: lg->xmin = 1.e20;
69: lg->ymin = 1.e20;
70: lg->xmax = -1.e20;
71: lg->ymax = -1.e20;
72: PetscMalloc(2*dim*CHUNCKSIZE*sizeof(PetscReal),&lg->x);
73: PetscLogObjectMemory(lg,2*dim*CHUNCKSIZE*sizeof(PetscReal));
74: lg->y = lg->x + dim*CHUNCKSIZE;
75: lg->len = dim*CHUNCKSIZE;
76: lg->loc = 0;
77: lg->use_dots= PETSC_FALSE;
78: PetscDrawAxisCreate(draw,&lg->axis);
79: PetscLogObjectParent(lg,lg->axis);
80: *outctx = lg;
81: return(0);
82: }
86: /*@
87: PetscDrawLGSetDimension - Change the number of lines that are to be drawn.
89: Collective over PetscDrawLG
91: Input Parameter:
92: + lg - the line graph context.
93: - dim - the number of curves.
95: Level: intermediate
97: Concepts: line graph^setting number of lines
99: @*/
100: PetscErrorCode PetscDrawLGSetDimension(PetscDrawLG lg,int dim)
101: {
105: if (lg && lg->cookie == PETSC_DRAW_COOKIE) return(0);
107: if (lg->dim == dim) return(0);
109: PetscFree(lg->x);
110: lg->dim = dim;
111: PetscMalloc(2*dim*CHUNCKSIZE*sizeof(PetscReal),&lg->x);
112: PetscLogObjectMemory(lg,2*dim*CHUNCKSIZE*sizeof(PetscReal));
113: lg->y = lg->x + dim*CHUNCKSIZE;
114: lg->len = dim*CHUNCKSIZE;
115: return(0);
116: }
120: /*@
121: PetscDrawLGReset - Clears line graph to allow for reuse with new data.
123: Collective over PetscDrawLG
125: Input Parameter:
126: . lg - the line graph context.
128: Level: intermediate
130: Concepts: line graph^restarting
132: @*/
133: PetscErrorCode PetscDrawLGReset(PetscDrawLG lg)
134: {
136: if (lg && lg->cookie == PETSC_DRAW_COOKIE) return(0);
138: lg->xmin = 1.e20;
139: lg->ymin = 1.e20;
140: lg->xmax = -1.e20;
141: lg->ymax = -1.e20;
142: lg->loc = 0;
143: lg->nopts = 0;
144: return(0);
145: }
149: /*@
150: PetscDrawLGDestroy - Frees all space taken up by line graph data structure.
152: Collective over PetscDrawLG
154: Input Parameter:
155: . lg - the line graph context
157: Level: intermediate
159: .seealso: PetscDrawLGCreate()
160: @*/
161: PetscErrorCode PetscDrawLGDestroy(PetscDrawLG lg)
162: {
166: if (!lg || lg->cookie != PETSC_DRAW_COOKIE) {
168: }
170: if (--lg->refct > 0) return(0);
171: if (lg && lg->cookie == PETSC_DRAW_COOKIE) {
172: PetscObjectDestroy((PetscObject)lg);
173: return(0);
174: }
175: PetscDrawAxisDestroy(lg->axis);
176: PetscFree(lg->x);
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: /*@
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: /*@
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: }