xref: /petsc/src/sys/classes/draw/utils/dscatter.c (revision ce94432eddcd14845bc7e8083b7f8ea723b9bf7d)
1 
2 /*
3        Contains the data structure for drawing scatter plots
4     graphs in a window with an axis. This is intended for scatter
5     plots that change dynamically.
6 */
7 
8 #include <petsc-private/petscimpl.h>         /*I "petscsys.h" I*/
9 
10 PetscClassId PETSC_DRAWSP_CLASSID = 0;
11 
12 struct _p_PetscDrawSP {
13   PETSCHEADER(int);
14   PetscErrorCode (*destroy)(PetscDrawSP);
15   PetscErrorCode (*view)(PetscDrawSP,PetscViewer);
16   int            len,loc;
17   PetscDraw      win;
18   PetscDrawAxis  axis;
19   PetscReal      xmin,xmax,ymin,ymax,*x,*y;
20   int            nopts,dim;
21 };
22 
23 #define CHUNCKSIZE 100
24 
25 #undef __FUNCT__
26 #define __FUNCT__ "PetscDrawSPCreate"
27 /*@C
28     PetscDrawSPCreate - Creates a scatter plot data structure.
29 
30     Collective over PetscDraw
31 
32     Input Parameters:
33 +   win - the window where the graph will be made.
34 -   dim - the number of sets of points which will be drawn
35 
36     Output Parameters:
37 .   drawsp - the scatter plot context
38 
39    Level: intermediate
40 
41    Concepts: scatter plot^creating
42 
43 .seealso:  PetscDrawSPDestroy()
44 @*/
45 PetscErrorCode  PetscDrawSPCreate(PetscDraw draw,int dim,PetscDrawSP *drawsp)
46 {
47   PetscErrorCode ierr;
48   PetscBool      isnull;
49   PetscObject    obj = (PetscObject)draw;
50   PetscDrawSP    sp;
51 
52   PetscFunctionBegin;
53   PetscValidHeaderSpecific(draw,PETSC_DRAW_CLASSID,1);
54   PetscValidPointer(drawsp,3);
55   ierr = PetscObjectTypeCompare(obj,PETSC_DRAW_NULL,&isnull);CHKERRQ(ierr);
56   if (isnull) {
57     ierr = PetscDrawOpenNull(PetscObjectComm((PetscObject)obj),(PetscDraw*)drawsp);CHKERRQ(ierr);
58     PetscFunctionReturn(0);
59   }
60   ierr = PetscHeaderCreate(sp,_p_PetscDrawSP,int,PETSC_DRAWSP_CLASSID,"PetscDrawSP","Scatter plot","Draw",PetscObjectComm((PetscObject)obj),PetscDrawSPDestroy,0);CHKERRQ(ierr);
61 
62   sp->view    = 0;
63   sp->destroy = 0;
64   sp->nopts   = 0;
65   sp->win     = draw;
66   sp->dim     = dim;
67   sp->xmin    = 1.e20;
68   sp->ymin    = 1.e20;
69   sp->xmax    = -1.e20;
70   sp->ymax    = -1.e20;
71 
72   ierr = PetscMalloc2(dim*CHUNCKSIZE,PetscReal,&sp->x,dim*CHUNCKSIZE,PetscReal,&sp->y);CHKERRQ(ierr);
73   ierr = PetscLogObjectMemory(sp,2*dim*CHUNCKSIZE*sizeof(PetscReal));CHKERRQ(ierr);
74 
75   sp->len     = dim*CHUNCKSIZE;
76   sp->loc     = 0;
77 
78   ierr = PetscDrawAxisCreate(draw,&sp->axis);CHKERRQ(ierr);
79   ierr = PetscLogObjectParent(sp,sp->axis);CHKERRQ(ierr);
80 
81   *drawsp = sp;
82   PetscFunctionReturn(0);
83 }
84 
85 #undef __FUNCT__
86 #define __FUNCT__ "PetscDrawSPSetDimension"
87 /*@
88    PetscDrawSPSetDimension - Change the number of sets of points  that are to be drawn.
89 
90    Not Collective (ignored on all processors except processor 0 of PetscDrawSP)
91 
92    Input Parameter:
93 +  sp - the line graph context.
94 -  dim - the number of curves.
95 
96    Level: intermediate
97 
98    Concepts: scatter plot^setting number of data types
99 
100 @*/
101 PetscErrorCode  PetscDrawSPSetDimension(PetscDrawSP sp,int dim)
102 {
103   PetscErrorCode ierr;
104 
105   PetscFunctionBegin;
106   if (sp && ((PetscObject)sp)->classid == PETSC_DRAW_CLASSID) PetscFunctionReturn(0);
107   PetscValidHeaderSpecific(sp,PETSC_DRAWSP_CLASSID,1);
108   if (sp->dim == dim) PetscFunctionReturn(0);
109 
110   ierr    = PetscFree2(sp->x,sp->y);CHKERRQ(ierr);
111   sp->dim = dim;
112   ierr    = PetscMalloc2(dim*CHUNCKSIZE,PetscReal,&sp->x,dim*CHUNCKSIZE,PetscReal,&sp->y);CHKERRQ(ierr);
113   ierr    = PetscLogObjectMemory(sp,2*dim*CHUNCKSIZE*sizeof(PetscReal));CHKERRQ(ierr);
114   sp->len = dim*CHUNCKSIZE;
115   PetscFunctionReturn(0);
116 }
117 
118 #undef __FUNCT__
119 #define __FUNCT__ "PetscDrawSPReset"
120 /*@
121    PetscDrawSPReset - Clears line graph to allow for reuse with new data.
122 
123    Not Collective (ignored on all processors except processor 0 of PetscDrawSP)
124 
125    Input Parameter:
126 .  sp - the line graph context.
127 
128    Level: intermediate
129 
130   Concepts: scatter plot^resetting
131 
132 @*/
133 PetscErrorCode  PetscDrawSPReset(PetscDrawSP sp)
134 {
135   PetscFunctionBegin;
136   if (sp && ((PetscObject)sp)->classid == PETSC_DRAW_CLASSID) PetscFunctionReturn(0);
137   PetscValidHeaderSpecific(sp,PETSC_DRAWSP_CLASSID,1);
138   sp->xmin  = 1.e20;
139   sp->ymin  = 1.e20;
140   sp->xmax  = -1.e20;
141   sp->ymax  = -1.e20;
142   sp->loc   = 0;
143   sp->nopts = 0;
144   PetscFunctionReturn(0);
145 }
146 
147 #undef __FUNCT__
148 #define __FUNCT__ "PetscDrawSPDestroy"
149 /*@C
150    PetscDrawSPDestroy - Frees all space taken up by scatter plot data structure.
151 
152    Collective over PetscDrawSP
153 
154    Input Parameter:
155 .  sp - the line graph context
156 
157    Level: intermediate
158 
159 .seealso:  PetscDrawSPCreate()
160 @*/
161 PetscErrorCode  PetscDrawSPDestroy(PetscDrawSP *sp)
162 {
163   PetscErrorCode ierr;
164 
165   PetscFunctionBegin;
166   if (!*sp) PetscFunctionReturn(0);
167   PetscValidHeader(*sp,1);
168 
169   if (--((PetscObject)(*sp))->refct > 0) PetscFunctionReturn(0);
170   if (((PetscObject)(*sp))->classid == PETSC_DRAW_CLASSID) {
171     ierr = PetscDrawDestroy((PetscDraw*) sp);CHKERRQ(ierr);
172     PetscFunctionReturn(0);
173   }
174   ierr = PetscDrawAxisDestroy(&(*sp)->axis);CHKERRQ(ierr);
175   ierr = PetscFree2((*sp)->x,(*sp)->y);CHKERRQ(ierr);
176   ierr = PetscHeaderDestroy(sp);CHKERRQ(ierr);
177   PetscFunctionReturn(0);
178 }
179 
180 #undef __FUNCT__
181 #define __FUNCT__ "PetscDrawSPAddPoint"
182 /*@
183    PetscDrawSPAddPoint - Adds another point to each of the scatter plots.
184 
185    Not Collective (ignored on all processors except processor 0 of PetscDrawSP)
186 
187    Input Parameters:
188 +  sp - the scatter plot data structure
189 -  x, y - the points to two vectors containing the new x and y
190           point for each curve.
191 
192    Level: intermediate
193 
194    Concepts: scatter plot^adding points
195 
196 .seealso: PetscDrawSPAddPoints()
197 @*/
198 PetscErrorCode  PetscDrawSPAddPoint(PetscDrawSP sp,PetscReal *x,PetscReal *y)
199 {
200   PetscErrorCode ierr;
201   PetscInt       i;
202 
203   PetscFunctionBegin;
204   if (sp && ((PetscObject)sp)->classid == PETSC_DRAW_CLASSID) PetscFunctionReturn(0);
205 
206   PetscValidHeaderSpecific(sp,PETSC_DRAWSP_CLASSID,1);
207   if (sp->loc+sp->dim >= sp->len) { /* allocate more space */
208     PetscReal *tmpx,*tmpy;
209     ierr     = PetscMalloc2(sp->len+sp->dim*CHUNCKSIZE,PetscReal,&tmpx,sp->len+sp->dim*CHUNCKSIZE,PetscReal,&tmpy);CHKERRQ(ierr);
210     ierr     = PetscLogObjectMemory(sp,2*sp->dim*CHUNCKSIZE*sizeof(PetscReal));CHKERRQ(ierr);
211     ierr     = PetscMemcpy(tmpx,sp->x,sp->len*sizeof(PetscReal));CHKERRQ(ierr);
212     ierr     = PetscMemcpy(tmpy,sp->y,sp->len*sizeof(PetscReal));CHKERRQ(ierr);
213     ierr     = PetscFree2(sp->x,sp->y);CHKERRQ(ierr);
214     sp->x    = tmpx;
215     sp->y    = tmpy;
216     sp->len += sp->dim*CHUNCKSIZE;
217   }
218   for (i=0; i<sp->dim; i++) {
219     if (x[i] > sp->xmax) sp->xmax = x[i];
220     if (x[i] < sp->xmin) sp->xmin = x[i];
221     if (y[i] > sp->ymax) sp->ymax = y[i];
222     if (y[i] < sp->ymin) sp->ymin = y[i];
223 
224     sp->x[sp->loc]   = x[i];
225     sp->y[sp->loc++] = y[i];
226   }
227   sp->nopts++;
228   PetscFunctionReturn(0);
229 }
230 
231 
232 #undef __FUNCT__
233 #define __FUNCT__ "PetscDrawSPAddPoints"
234 /*@C
235    PetscDrawSPAddPoints - Adds several points to each of the scatter plots.
236 
237    Not Collective (ignored on all processors except processor 0 of PetscDrawSP)
238 
239    Input Parameters:
240 +  sp - the LineGraph data structure
241 .  xx,yy - points to two arrays of pointers that point to arrays
242            containing the new x and y points for each curve.
243 -  n - number of points being added
244 
245    Level: intermediate
246 
247    Concepts: scatter plot^adding points
248 
249 .seealso: PetscDrawSPAddPoint()
250 @*/
251 PetscErrorCode  PetscDrawSPAddPoints(PetscDrawSP sp,int n,PetscReal **xx,PetscReal **yy)
252 {
253   PetscErrorCode ierr;
254   PetscInt       i,j,k;
255   PetscReal      *x,*y;
256 
257   PetscFunctionBegin;
258   if (sp && ((PetscObject)sp)->classid == PETSC_DRAW_CLASSID) PetscFunctionReturn(0);
259   PetscValidHeaderSpecific(sp,PETSC_DRAWSP_CLASSID,1);
260 
261   if (sp->loc+n*sp->dim >= sp->len) { /* allocate more space */
262     PetscReal *tmpx,*tmpy;
263     PetscInt  chunk = CHUNCKSIZE;
264     if (n > chunk) chunk = n;
265     ierr = PetscMalloc2(sp->len+sp->dim*chunk,PetscReal,&tmpx,sp->len+sp->dim*chunk,PetscReal,&tmpy);CHKERRQ(ierr);
266     ierr = PetscLogObjectMemory(sp,2*sp->dim*CHUNCKSIZE*sizeof(PetscReal));CHKERRQ(ierr);
267     ierr = PetscMemcpy(tmpx,sp->x,sp->len*sizeof(PetscReal));CHKERRQ(ierr);
268     ierr = PetscMemcpy(tmpy,sp->y,sp->len*sizeof(PetscReal));CHKERRQ(ierr);
269     ierr = PetscFree2(sp->x,sp->y);CHKERRQ(ierr);
270 
271     sp->x    = tmpx;
272     sp->y    = tmpy;
273     sp->len += sp->dim*CHUNCKSIZE;
274   }
275   for (j=0; j<sp->dim; j++) {
276     x = xx[j]; y = yy[j];
277     k = sp->loc + j;
278     for (i=0; i<n; i++) {
279       if (x[i] > sp->xmax) sp->xmax = x[i];
280       if (x[i] < sp->xmin) sp->xmin = x[i];
281       if (y[i] > sp->ymax) sp->ymax = y[i];
282       if (y[i] < sp->ymin) sp->ymin = y[i];
283 
284       sp->x[k] = x[i];
285       sp->y[k] = y[i];
286       k       += sp->dim;
287     }
288   }
289   sp->loc   += n*sp->dim;
290   sp->nopts += n;
291   PetscFunctionReturn(0);
292 }
293 
294 #undef __FUNCT__
295 #define __FUNCT__ "PetscDrawSPDraw"
296 /*@
297    PetscDrawSPDraw - Redraws a scatter plot.
298 
299    Not Collective (ignored on all processors except processor 0 of PetscDrawSP)
300 
301    Input Parameter:
302 +  sp - the line graph context
303 -  clear - clear the window before drawing the new plot
304 
305    Level: intermediate
306 
307 .seealso: PetscDrawLGDraw(), PetscDrawLGSPDraw()
308 
309 @*/
310 PetscErrorCode  PetscDrawSPDraw(PetscDrawSP sp, PetscBool clear)
311 {
312   PetscReal      xmin=sp->xmin,xmax=sp->xmax,ymin=sp->ymin,ymax=sp->ymax;
313   PetscErrorCode ierr;
314   PetscInt       i,j,dim = sp->dim,nopts = sp->nopts;
315   PetscMPIInt    rank;
316   PetscDraw      draw = sp->win;
317 
318   PetscFunctionBegin;
319   if (sp && ((PetscObject)sp)->classid == PETSC_DRAW_CLASSID) PetscFunctionReturn(0);
320   PetscValidHeaderSpecific(sp,PETSC_DRAWSP_CLASSID,1);
321 
322   if (nopts < 1) PetscFunctionReturn(0);
323   if (xmin > xmax || ymin > ymax) PetscFunctionReturn(0);
324   if (clear) {
325     ierr = PetscDrawCheckResizedWindow(draw);CHKERRQ(ierr);
326     ierr = PetscDrawClear(draw);CHKERRQ(ierr);
327   }
328   ierr = PetscDrawAxisSetLimits(sp->axis,xmin,xmax,ymin,ymax);CHKERRQ(ierr);
329   ierr = PetscDrawAxisDraw(sp->axis);CHKERRQ(ierr);
330 
331   ierr = MPI_Comm_rank(PetscObjectComm((PetscObject)sp),&rank);CHKERRQ(ierr);
332   if (!rank) {
333     for (i=0; i<dim; i++) {
334       for (j=0; j<nopts; j++) {
335         ierr = PetscDrawPoint(draw,sp->x[j*dim+i],sp->y[j*dim+i],PETSC_DRAW_RED);CHKERRQ(ierr);
336       }
337     }
338   }
339   ierr = PetscDrawFlush(sp->win);CHKERRQ(ierr);
340   ierr = PetscDrawPause(sp->win);CHKERRQ(ierr);
341   PetscFunctionReturn(0);
342 }
343 
344 #undef __FUNCT__
345 #define __FUNCT__ "PetscDrawSPSetLimits"
346 /*@
347    PetscDrawSPSetLimits - 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.
350 
351    Not Collective (ignored on all processors except processor 0 of PetscDrawSP)
352 
353    Input Parameters:
354 +  xsp - the line graph context
355 -  x_min,x_max,y_min,y_max - the limits
356 
357    Level: intermediate
358 
359    Concepts: scatter plot^setting axis
360 
361 @*/
362 PetscErrorCode  PetscDrawSPSetLimits(PetscDrawSP sp,PetscReal x_min,PetscReal x_max,PetscReal y_min,PetscReal y_max)
363 {
364   PetscFunctionBegin;
365   if (sp && ((PetscObject)sp)->classid == PETSC_DRAW_CLASSID) PetscFunctionReturn(0);
366   PetscValidHeaderSpecific(sp,PETSC_DRAWSP_CLASSID,1);
367   sp->xmin = x_min;
368   sp->xmax = x_max;
369   sp->ymin = y_min;
370   sp->ymax = y_max;
371   PetscFunctionReturn(0);
372 }
373 
374 #undef __FUNCT__
375 #define __FUNCT__ "PetscDrawSPGetAxis"
376 /*@C
377    PetscDrawSPGetAxis - Gets the axis context associated with a line graph.
378    This is useful if one wants to change some axis property, such as
379    labels, color, etc. The axis context should not be destroyed by the
380    application code.
381 
382    Not Collective (except PetscDrawAxis can only be used on processor 0 of PetscDrawSP)
383 
384    Input Parameter:
385 .  sp - the line graph context
386 
387    Output Parameter:
388 .  axis - the axis context
389 
390    Level: intermediate
391 
392 @*/
393 PetscErrorCode  PetscDrawSPGetAxis(PetscDrawSP sp,PetscDrawAxis *axis)
394 {
395   PetscFunctionBegin;
396   if (sp && ((PetscObject)sp)->classid == PETSC_DRAW_CLASSID) {
397     *axis = 0;
398     PetscFunctionReturn(0);
399   }
400   PetscValidHeaderSpecific(sp,PETSC_DRAWSP_CLASSID,1);
401   *axis = sp->axis;
402   PetscFunctionReturn(0);
403 }
404 
405 #undef __FUNCT__
406 #define __FUNCT__ "PetscDrawSPGetDraw"
407 /*@C
408    PetscDrawSPGetDraw - Gets the draw context associated with a line graph.
409 
410    Not Collective, PetscDraw is parallel if PetscDrawSP is parallel
411 
412    Input Parameter:
413 .  sp - the line graph context
414 
415    Output Parameter:
416 .  draw - the draw context
417 
418    Level: intermediate
419 
420 @*/
421 PetscErrorCode  PetscDrawSPGetDraw(PetscDrawSP sp,PetscDraw *draw)
422 {
423   PetscFunctionBegin;
424   PetscValidHeader(sp,1);
425   PetscValidPointer(draw,2);
426   if (sp && ((PetscObject)sp)->classid == PETSC_DRAW_CLASSID) *draw = (PetscDraw)sp;
427   else *draw = sp->win;
428   PetscFunctionReturn(0);
429 }
430