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: /*@C
     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 PETSC_DLLEXPORT 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 PETSC_DLLEXPORT 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 PETSC_DLLEXPORT 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: /*@C
    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 PETSC_DLLEXPORT 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 PETSC_DLLEXPORT 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 PETSC_DLLEXPORT 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 PETSC_DLLEXPORT 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 PETSC_DLLEXPORT 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 PETSC_DLLEXPORT 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 PETSC_DLLEXPORT 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 PETSC_DLLEXPORT 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 PETSC_DLLEXPORT 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 PETSC_DLLEXPORT 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: }