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 petscsys.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 curves 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(((PetscObject)obj)->comm,(PetscDraw*)outctx);
60: return(0);
61: }
62: PetscHeaderCreate(lg,_p_DrawLG,int,DRAWLG_COOKIE,0,"PetscDrawLG",((PetscObject)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: PetscMalloc2(dim*CHUNCKSIZE,PetscReal,&lg->x,dim*CHUNCKSIZE,PetscReal,&lg->y);
73: PetscLogObjectMemory(lg,2*dim*CHUNCKSIZE*sizeof(PetscReal));
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 && ((PetscObject)lg)->cookie == PETSC_DRAW_COOKIE) return(0);
106: if (lg->dim == dim) return(0);
108: PetscFree2(lg->x,lg->y);
109: lg->dim = dim;
110: PetscMalloc2(dim*CHUNCKSIZE,PetscReal,&lg->x,dim*CHUNCKSIZE,PetscReal,&lg->y);
111: PetscLogObjectMemory(lg,2*dim*CHUNCKSIZE*sizeof(PetscReal));
112: lg->len = dim*CHUNCKSIZE;
113: return(0);
114: }
118: /*@
119: PetscDrawLGReset - Clears line graph to allow for reuse with new data.
121: Collective over PetscDrawLG
123: Input Parameter:
124: . lg - the line graph context.
126: Level: intermediate
128: Concepts: line graph^restarting
130: @*/
131: PetscErrorCode PetscDrawLGReset(PetscDrawLG lg)
132: {
134: if (lg && ((PetscObject)lg)->cookie == PETSC_DRAW_COOKIE) return(0);
136: lg->xmin = 1.e20;
137: lg->ymin = 1.e20;
138: lg->xmax = -1.e20;
139: lg->ymax = -1.e20;
140: lg->loc = 0;
141: lg->nopts = 0;
142: return(0);
143: }
147: /*@
148: PetscDrawLGDestroy - Frees all space taken up by line graph data structure.
150: Collective over PetscDrawLG
152: Input Parameter:
153: . lg - the line graph context
155: Level: intermediate
157: .seealso: PetscDrawLGCreate()
158: @*/
159: PetscErrorCode PetscDrawLGDestroy(PetscDrawLG lg)
160: {
164: if (!lg || ((PetscObject)lg)->cookie != PETSC_DRAW_COOKIE) {
166: }
168: if (--((PetscObject)lg)->refct > 0) return(0);
169: if (lg && ((PetscObject)lg)->cookie == PETSC_DRAW_COOKIE) {
170: PetscObjectDestroy((PetscObject)lg);
171: return(0);
172: }
173: PetscDrawAxisDestroy(lg->axis);
174: PetscFree2(lg->x,lg->y);
175: PetscHeaderDestroy(lg);
176: return(0);
177: }
181: /*@
182: PetscDrawLGAddPoint - Adds another point to each of the line graphs.
183: The new point must have an X coordinate larger than the old points.
185: Not Collective, but ignored by all processors except processor 0 in PetscDrawLG
187: Input Parameters:
188: + lg - the LineGraph data structure
189: - x, y - the points to two vectors containing the new x and y
190: point for each curve.
192: Level: intermediate
194: Concepts: line graph^adding points
196: .seealso: PetscDrawLGAddPoints()
197: @*/
198: PetscErrorCode PetscDrawLGAddPoint(PetscDrawLG lg,PetscReal *x,PetscReal *y)
199: {
201: int i;
204: if (lg && ((PetscObject)lg)->cookie == PETSC_DRAW_COOKIE) return(0);
207: if (lg->loc+lg->dim >= lg->len) { /* allocate more space */
208: PetscReal *tmpx,*tmpy;
209: PetscMalloc2(lg->len+lg->dim*CHUNCKSIZE,PetscReal,&tmpx,lg->len+lg->dim*CHUNCKSIZE,PetscReal,&tmpy);
210: PetscLogObjectMemory(lg,2*lg->dim*CHUNCKSIZE*sizeof(PetscReal));
211: PetscMemcpy(tmpx,lg->x,lg->len*sizeof(PetscReal));
212: PetscMemcpy(tmpy,lg->y,lg->len*sizeof(PetscReal));
213: PetscFree2(lg->x,lg->y);
214: lg->x = tmpx;
215: lg->y = tmpy;
216: lg->len += lg->dim*CHUNCKSIZE;
217: }
218: for (i=0; i<lg->dim; i++) {
219: if (x[i] > lg->xmax) lg->xmax = x[i];
220: if (x[i] < lg->xmin) lg->xmin = x[i];
221: if (y[i] > lg->ymax) lg->ymax = y[i];
222: if (y[i] < lg->ymin) lg->ymin = y[i];
224: lg->x[lg->loc] = x[i];
225: lg->y[lg->loc++] = y[i];
226: }
227: lg->nopts++;
228: return(0);
229: }
233: /*@
234: PetscDrawLGIndicateDataPoints - Causes LG to draw a big dot for each data-point.
236: Not Collective, but ignored by all processors except processor 0 in PetscDrawLG
238: Input Parameters:
239: . lg - the linegraph context
241: Level: intermediate
243: Concepts: line graph^showing points
245: @*/
246: PetscErrorCode PetscDrawLGIndicateDataPoints(PetscDrawLG lg)
247: {
249: if (lg && ((PetscObject)lg)->cookie == PETSC_DRAW_COOKIE) return(0);
251: lg->use_dots = PETSC_TRUE;
252: return(0);
253: }
257: /*@C
258: PetscDrawLGAddPoints - Adds several points to each of the line graphs.
259: The new points must have an X coordinate larger than the old points.
261: Not Collective, but ignored by all processors except processor 0 in PetscDrawLG
263: Input Parameters:
264: + lg - the LineGraph data structure
265: . xx,yy - points to two arrays of pointers that point to arrays
266: containing the new x and y points for each curve.
267: - n - number of points being added
269: Level: intermediate
272: Concepts: line graph^adding points
274: .seealso: PetscDrawLGAddPoint()
275: @*/
276: PetscErrorCode PetscDrawLGAddPoints(PetscDrawLG lg,int n,PetscReal **xx,PetscReal **yy)
277: {
279: int i,j,k;
280: PetscReal *x,*y;
283: if (lg && ((PetscObject)lg)->cookie == PETSC_DRAW_COOKIE) return(0);
285: if (lg->loc+n*lg->dim >= lg->len) { /* allocate more space */
286: PetscReal *tmpx,*tmpy;
287: int chunk = CHUNCKSIZE;
289: if (n > chunk) chunk = n;
290: PetscMalloc2(lg->len+lg->dim*chunk,PetscReal,&tmpx,lg->len+lg->dim*chunk,PetscReal,&tmpy);
291: PetscLogObjectMemory(lg,2*lg->dim*chunk*sizeof(PetscReal));
292: PetscMemcpy(tmpx,lg->x,lg->len*sizeof(PetscReal));
293: PetscMemcpy(tmpy,lg->y,lg->len*sizeof(PetscReal));
294: PetscFree2(lg->x,lg->y);
295: lg->x = tmpx;
296: lg->y = tmpy;
297: lg->len += lg->dim*chunk;
298: }
299: for (j=0; j<lg->dim; j++) {
300: x = xx[j]; y = yy[j];
301: k = lg->loc + j;
302: for (i=0; i<n; i++) {
303: if (x[i] > lg->xmax) lg->xmax = x[i];
304: if (x[i] < lg->xmin) lg->xmin = x[i];
305: if (y[i] > lg->ymax) lg->ymax = y[i];
306: if (y[i] < lg->ymin) lg->ymin = y[i];
308: lg->x[k] = x[i];
309: lg->y[k] = y[i];
310: k += lg->dim;
311: }
312: }
313: lg->loc += n*lg->dim;
314: lg->nopts += n;
315: return(0);
316: }
320: /*@
321: PetscDrawLGDraw - Redraws a line graph.
323: Not Collective,but ignored by all processors except processor 0 in PetscDrawLG
325: Input Parameter:
326: . lg - the line graph context
328: Level: intermediate
330: .seealso: PetscDrawSPDraw(), PetscDrawLGSPDraw()
332: @*/
333: PetscErrorCode PetscDrawLGDraw(PetscDrawLG lg)
334: {
335: PetscReal xmin=lg->xmin,xmax=lg->xmax,ymin=lg->ymin,ymax=lg->ymax;
337: int i,j,dim = lg->dim,nopts = lg->nopts,rank;
338: PetscDraw draw = lg->win;
341: if (lg && ((PetscObject)lg)->cookie == PETSC_DRAW_COOKIE) return(0);
344: PetscDrawClear(draw);
345: PetscDrawAxisSetLimits(lg->axis,xmin,xmax,ymin,ymax);
346: PetscDrawAxisDraw(lg->axis);
348: MPI_Comm_rank(((PetscObject)lg)->comm,&rank);
349: if (!rank) {
350:
351: for (i=0; i<dim; i++) {
352: for (j=1; j<nopts; j++) {
353: 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);
354: if (lg->use_dots) {
355: PetscDrawString(draw,lg->x[j*dim+i],lg->y[j*dim+i],PETSC_DRAW_RED,"x");
356: }
357: }
358: }
359: }
360: PetscDrawFlush(lg->win);
361: PetscDrawPause(lg->win);
362: return(0);
363: }
367: /*@
368: PetscDrawLGPrint - Prints a line graph.
370: Not collective
372: Input Parameter:
373: . lg - the line graph context
375: Level: beginner
377: Contributed by Matthew Knepley
379: .keywords: draw, line, graph
380: @*/
381: PetscErrorCode PetscDrawLGPrint(PetscDrawLG lg)
382: {
383: PetscReal xmin=lg->xmin, xmax=lg->xmax, ymin=lg->ymin, ymax=lg->ymax;
384: int i, j, dim = lg->dim, nopts = lg->nopts;
387: if (lg && ((PetscObject)lg)->cookie == PETSC_DRAW_COOKIE) return(0);
389: if (nopts < 1) return(0);
390: if (xmin > xmax || ymin > ymax) return(0);
392: for(i = 0; i < dim; i++) {
393: PetscPrintf(((PetscObject)lg)->comm, "Line %d>\n", i);
394: for(j = 0; j < nopts; j++) {
395: PetscPrintf(((PetscObject)lg)->comm, " X: %G Y: %G\n", lg->x[j*dim+i], lg->y[j*dim+i]);
396: }
397: }
398: return(0);
399: }
400:
403: /*@
404: PetscDrawLGSetLimits - Sets the axis limits for a line graph. If more
405: points are added after this call, the limits will be adjusted to
406: include those additional points.
408: Not Collective, but ignored by all processors except processor 0 in PetscDrawLG
410: Input Parameters:
411: + xlg - the line graph context
412: - x_min,x_max,y_min,y_max - the limits
414: Level: intermediate
416: Concepts: line graph^setting axis
418: @*/
419: PetscErrorCode PetscDrawLGSetLimits(PetscDrawLG lg,PetscReal x_min,PetscReal x_max,PetscReal y_min,PetscReal y_max)
420: {
422: if (lg && ((PetscObject)lg)->cookie == PETSC_DRAW_COOKIE) return(0);
424: (lg)->xmin = x_min;
425: (lg)->xmax = x_max;
426: (lg)->ymin = y_min;
427: (lg)->ymax = y_max;
428: return(0);
429: }
430:
433: /*@
434: PetscDrawLGGetAxis - Gets the axis context associated with a line graph.
435: This is useful if one wants to change some axis property, such as
436: labels, color, etc. The axis context should not be destroyed by the
437: application code.
439: Not Collective, if PetscDrawLG is parallel then PetscDrawAxis is parallel
441: Input Parameter:
442: . lg - the line graph context
444: Output Parameter:
445: . axis - the axis context
447: Level: advanced
449: @*/
450: PetscErrorCode PetscDrawLGGetAxis(PetscDrawLG lg,PetscDrawAxis *axis)
451: {
453: if (lg && ((PetscObject)lg)->cookie == PETSC_DRAW_COOKIE) {
454: *axis = 0;
455: return(0);
456: }
459: *axis = lg->axis;
460: return(0);
461: }
465: /*@
466: PetscDrawLGGetDraw - Gets the draw context associated with a line graph.
468: Not Collective, if PetscDrawLG is parallel then PetscDraw is parallel
470: Input Parameter:
471: . lg - the line graph context
473: Output Parameter:
474: . draw - the draw context
476: Level: intermediate
478: @*/
479: PetscErrorCode PetscDrawLGGetDraw(PetscDrawLG lg,PetscDraw *draw)
480: {
484: if (((PetscObject)lg)->cookie == PETSC_DRAW_COOKIE) {
485: *draw = (PetscDraw)lg;
486: } else {
488: *draw = lg->win;
489: }
490: return(0);
491: }
496: /*@
497: PetscDrawLGSPDraw - Redraws a line graph.
499: Not Collective,but ignored by all processors except processor 0 in PetscDrawLG
501: Input Parameter:
502: . lg - the line graph context
504: Level: intermediate
506: .seealso: PetscDrawLGDraw(), PetscDrawSPDraw()
508: Developer Notes: This code cheats and uses the fact that the LG and SP structs are the same
510: @*/
511: PetscErrorCode PetscDrawLGSPDraw(PetscDrawLG lg,PetscDrawSP spin)
512: {
513: PetscDrawLG sp = (PetscDrawLG)spin;
514: PetscReal xmin,xmax,ymin,ymax;
516: int i,j,dim,nopts,rank;
517: PetscDraw draw = lg->win;
520: if (lg && ((PetscObject)lg)->cookie == PETSC_DRAW_COOKIE) return(0);
524: xmin = PetscMin(lg->xmin,sp->xmin);
525: ymin = PetscMin(lg->ymin,sp->ymin);
526: xmax = PetscMax(lg->xmax,sp->xmax);
527: ymax = PetscMax(lg->ymax,sp->ymax);
529: PetscDrawClear(draw);
530: PetscDrawAxisSetLimits(lg->axis,xmin,xmax,ymin,ymax);
531: PetscDrawAxisDraw(lg->axis);
533: MPI_Comm_rank(((PetscObject)lg)->comm,&rank);
534: if (!rank) {
535:
536: dim = lg->dim;
537: nopts = lg->nopts;
538: for (i=0; i<dim; i++) {
539: for (j=1; j<nopts; j++) {
540: 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);
541: if (lg->use_dots) {
542: PetscDrawString(draw,lg->x[j*dim+i],lg->y[j*dim+i],PETSC_DRAW_RED,"x");
543: }
544: }
545: }
547: dim = sp->dim;
548: nopts = sp->nopts;
549: for (i=0; i<dim; i++) {
550: for (j=0; j<nopts; j++) {
551: PetscDrawString(draw,sp->x[j*dim+i],sp->y[j*dim+i],PETSC_DRAW_RED,"x");
552: }
553: }
554: }
555: PetscDrawFlush(lg->win);
556: PetscDrawPause(lg->win);
557: return(0);
558: }