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