Actual source code: lgc.c

      2: #include <petscviewer.h>
      3: #include <petsc/private/drawimpl.h>
      4: PetscClassId PETSC_DRAWLG_CLASSID = 0;

      6: /*@
      7:    PetscDrawLGGetAxis - Gets the axis context associated with a line graph.
      8:    This is useful if one wants to change some axis property, such as
      9:    labels, color, etc. The axis context should not be destroyed by the
     10:    application code.

     12:    Not Collective, if PetscDrawLG is parallel then PetscDrawAxis is parallel

     14:    Input Parameter:
     15: .  lg - the line graph context

     17:    Output Parameter:
     18: .  axis - the axis context

     20:    Level: advanced

     22: .seealso: PetscDrawLGCreate(), PetscDrawAxis

     24: @*/
     25: PetscErrorCode  PetscDrawLGGetAxis(PetscDrawLG lg,PetscDrawAxis *axis)
     26: {
     29:   *axis = lg->axis;
     30:   return 0;
     31: }

     33: /*@
     34:    PetscDrawLGGetDraw - Gets the draw context associated with a line graph.

     36:    Not Collective, if PetscDrawLG is parallel then PetscDraw is parallel

     38:    Input Parameter:
     39: .  lg - the line graph context

     41:    Output Parameter:
     42: .  draw - the draw context

     44:    Level: intermediate

     46: .seealso: PetscDrawLGCreate(), PetscDraw
     47: @*/
     48: PetscErrorCode  PetscDrawLGGetDraw(PetscDrawLG lg,PetscDraw *draw)
     49: {
     52:   *draw = lg->win;
     53:   return 0;
     54: }

     56: /*@
     57:    PetscDrawLGSPDraw - Redraws a line graph.

     59:    Collective on PetscDrawLG

     61:    Input Parameter:
     62: .  lg - the line graph context

     64:    Level: intermediate

     66: .seealso: PetscDrawLGDraw(), PetscDrawSPDraw()

     68:    Developer Notes:
     69:     This code cheats and uses the fact that the LG and SP structs are the same

     71: @*/
     72: PetscErrorCode  PetscDrawLGSPDraw(PetscDrawLG lg,PetscDrawSP spin)
     73: {
     74:   PetscDrawLG    sp = (PetscDrawLG)spin;
     75:   PetscReal      xmin,xmax,ymin,ymax;
     76:   PetscBool      isnull;
     77:   PetscMPIInt    rank;
     78:   PetscDraw      draw;

     83:   PetscDrawIsNull(lg->win,&isnull);
     84:   if (isnull) return 0;
     85:   MPI_Comm_rank(PetscObjectComm((PetscObject)lg),&rank);

     87:   draw = lg->win;
     88:   PetscDrawCheckResizedWindow(draw);
     89:   PetscDrawClear(draw);

     91:   xmin = PetscMin(lg->xmin,sp->xmin); ymin = PetscMin(lg->ymin,sp->ymin);
     92:   xmax = PetscMax(lg->xmax,sp->xmax); ymax = PetscMax(lg->ymax,sp->ymax);
     93:   PetscDrawAxisSetLimits(lg->axis,xmin,xmax,ymin,ymax);
     94:   PetscDrawAxisDraw(lg->axis);

     96:   PetscDrawCollectiveBegin(draw);
     97:   if (rank == 0) {
     98:     int i,j,dim,nopts;
     99:     dim   = lg->dim;
    100:     nopts = lg->nopts;
    101:     for (i=0; i<dim; i++) {
    102:       for (j=1; j<nopts; j++) {
    103:         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);
    104:         if (lg->use_markers) {
    105:           PetscDrawMarker(draw,lg->x[j*dim+i],lg->y[j*dim+i],PETSC_DRAW_RED);
    106:         }
    107:       }
    108:     }
    109:     dim   = sp->dim;
    110:     nopts = sp->nopts;
    111:     for (i=0; i<dim; i++) {
    112:       for (j=0; j<nopts; j++) {
    113:         PetscDrawMarker(draw,sp->x[j*dim+i],sp->y[j*dim+i],PETSC_DRAW_RED);
    114:       }
    115:     }
    116:   }
    117:   PetscDrawCollectiveEnd(draw);

    119:   PetscDrawFlush(draw);
    120:   PetscDrawPause(draw);
    121:   return 0;
    122: }

    124: /*@
    125:     PetscDrawLGCreate - Creates a line graph data structure.

    127:     Collective on PetscDraw

    129:     Input Parameters:
    130: +   draw - the window where the graph will be made.
    131: -   dim - the number of curves which will be drawn

    133:     Output Parameters:
    134: .   outlg - the line graph context

    136:     Level: intermediate

    138:     Notes:
    139:     The MPI communicator that owns the PetscDraw owns this PetscDrawLG, but the calls to set options and add points are ignored on all processes except the
    140:            zeroth MPI process in the communicator. All MPI processes in the communicator must call PetscDrawLGDraw() to display the updated graph.

    142: .seealso:  PetscDrawLGDestroy(), PetscDrawLGAddPoint(), PetscDrawLGAddCommonPoint(), PetscDrawLGAddPoints(), PetscDrawLGDraw(), PetscDrawLGSave(),
    143:            PetscDrawLGView(), PetscDrawLGReset(), PetscDrawLGSetDimension(), PetscDrawLGGetDimension(), PetscDrawLGSetLegend(), PetscDrawLGGetAxis(),
    144:            PetscDrawLGGetDraw(), PetscDrawLGSetUseMarkers(), PetscDrawLGSetLimits(), PetscDrawLGSetColors(), PetscDrawLGSetOptionsPrefix(), PetscDrawLGSetFromOptions()
    145: @*/
    146: PetscErrorCode  PetscDrawLGCreate(PetscDraw draw,PetscInt dim,PetscDrawLG *outlg)
    147: {
    148:   PetscDrawLG    lg;

    154:   PetscHeaderCreate(lg,PETSC_DRAWLG_CLASSID,"DrawLG","Line Graph","Draw",PetscObjectComm((PetscObject)draw),PetscDrawLGDestroy,NULL);
    155:   PetscLogObjectParent((PetscObject)draw,(PetscObject)lg);
    156:   PetscDrawLGSetOptionsPrefix(lg,((PetscObject)draw)->prefix);

    158:   PetscObjectReference((PetscObject)draw);
    159:   lg->win = draw;

    161:   lg->view    = NULL;
    162:   lg->destroy = NULL;
    163:   lg->nopts   = 0;
    164:   lg->dim     = dim;
    165:   lg->xmin    = 1.e20;
    166:   lg->ymin    = 1.e20;
    167:   lg->xmax    = -1.e20;
    168:   lg->ymax    = -1.e20;

    170:   PetscMalloc2(dim*PETSC_DRAW_LG_CHUNK_SIZE,&lg->x,dim*PETSC_DRAW_LG_CHUNK_SIZE,&lg->y);
    171:   PetscLogObjectMemory((PetscObject)lg,2*dim*PETSC_DRAW_LG_CHUNK_SIZE*sizeof(PetscReal));

    173:   lg->len         = dim*PETSC_DRAW_LG_CHUNK_SIZE;
    174:   lg->loc         = 0;
    175:   lg->use_markers = PETSC_FALSE;

    177:   PetscDrawAxisCreate(draw,&lg->axis);
    178:   PetscLogObjectParent((PetscObject)lg,(PetscObject)lg->axis);

    180:   *outlg = lg;
    181:   return 0;
    182: }

    184: /*@
    185:    PetscDrawLGSetColors - Sets the color of each line graph drawn

    187:    Logically Collective on PetscDrawLG

    189:    Input Parameters:
    190: +  lg - the line graph context.
    191: -  colors - the colors

    193:    Level: intermediate

    195: .seealso: PetscDrawLGCreate()

    197: @*/
    198: PetscErrorCode  PetscDrawLGSetColors(PetscDrawLG lg,const int colors[])
    199: {

    203:   PetscFree(lg->colors);
    204:   PetscMalloc1(lg->dim,&lg->colors);
    205:   PetscArraycpy(lg->colors,colors,lg->dim);
    206:   return 0;
    207: }

    209: /*@C
    210:    PetscDrawLGSetLegend - sets the names of each curve plotted

    212:    Logically Collective on PetscDrawLG

    214:    Input Parameters:
    215: +  lg - the line graph context.
    216: -  names - the names for each curve

    218:    Level: intermediate

    220:    Notes:
    221:     Call PetscDrawLGGetAxis() and then change properties of the PetscDrawAxis for detailed control of the plot

    223: .seealso: PetscDrawLGGetAxis(), PetscDrawAxis, PetscDrawAxisSetColors(), PetscDrawAxisSetLabels(), PetscDrawAxisSetHoldLimits()

    225: @*/
    226: PetscErrorCode  PetscDrawLGSetLegend(PetscDrawLG lg,const char *const *names)
    227: {
    228:   PetscInt       i;

    233:   if (lg->legend) {
    234:     for (i=0; i<lg->dim; i++) {
    235:       PetscFree(lg->legend[i]);
    236:     }
    237:     PetscFree(lg->legend);
    238:   }
    239:   if (names) {
    240:     PetscMalloc1(lg->dim,&lg->legend);
    241:     for (i=0; i<lg->dim; i++) {
    242:       PetscStrallocpy(names[i],&lg->legend[i]);
    243:     }
    244:   }
    245:   return 0;
    246: }

    248: /*@
    249:    PetscDrawLGGetDimension - Change the number of lines that are to be drawn.

    251:    Not Collective

    253:    Input Parameter:
    254: .  lg - the line graph context.

    256:    Output Parameter:
    257: .  dim - the number of curves.

    259:    Level: intermediate

    261: .seealso: PetscDrawLGCreate(), PetscDrawLGSetDimension()

    263: @*/
    264: PetscErrorCode  PetscDrawLGGetDimension(PetscDrawLG lg,PetscInt *dim)
    265: {
    268:   *dim = lg->dim;
    269:   return 0;
    270: }

    272: /*@
    273:    PetscDrawLGSetDimension - Change the number of lines that are to be drawn.

    275:    Logically Collective on PetscDrawLG

    277:    Input Parameters:
    278: +  lg - the line graph context.
    279: -  dim - the number of curves.

    281:    Level: intermediate

    283: .seealso: PetscDrawLGCreate(), PetscDrawLGGetDimension()
    284: @*/
    285: PetscErrorCode  PetscDrawLGSetDimension(PetscDrawLG lg,PetscInt dim)
    286: {
    287:   PetscInt       i;

    291:   if (lg->dim == dim) return 0;

    293:   PetscFree2(lg->x,lg->y);
    294:   if (lg->legend) {
    295:     for (i=0; i<lg->dim; i++) {
    296:       PetscFree(lg->legend[i]);
    297:     }
    298:     PetscFree(lg->legend);
    299:   }
    300:   PetscFree(lg->colors);
    301:   lg->dim = dim;
    302:   PetscMalloc2(dim*PETSC_DRAW_LG_CHUNK_SIZE,&lg->x,dim*PETSC_DRAW_LG_CHUNK_SIZE,&lg->y);
    303:   PetscLogObjectMemory((PetscObject)lg,2*dim*PETSC_DRAW_LG_CHUNK_SIZE*sizeof(PetscReal));
    304:   lg->len = dim*PETSC_DRAW_LG_CHUNK_SIZE;
    305:   return 0;
    306: }

    308: /*@
    309:    PetscDrawLGSetLimits - Sets the axis limits for a line graph. If more
    310:    points are added after this call, the limits will be adjusted to
    311:    include those additional points.

    313:    Logically Collective on PetscDrawLG

    315:    Input Parameters:
    316: +  xlg - the line graph context
    317: -  x_min,x_max,y_min,y_max - the limits

    319:    Level: intermediate

    321: .seealso: PetscDrawLGCreate()

    323: @*/
    324: PetscErrorCode  PetscDrawLGSetLimits(PetscDrawLG lg,PetscReal x_min,PetscReal x_max,PetscReal y_min,PetscReal y_max)
    325: {

    328:   (lg)->xmin = x_min;
    329:   (lg)->xmax = x_max;
    330:   (lg)->ymin = y_min;
    331:   (lg)->ymax = y_max;
    332:   return 0;
    333: }

    335: /*@
    336:    PetscDrawLGReset - Clears line graph to allow for reuse with new data.

    338:    Logically Collective on PetscDrawLG

    340:    Input Parameter:
    341: .  lg - the line graph context.

    343:    Level: intermediate

    345: .seealso: PetscDrawLGCreate()
    346: @*/
    347: PetscErrorCode  PetscDrawLGReset(PetscDrawLG lg)
    348: {
    350:   lg->xmin  = 1.e20;
    351:   lg->ymin  = 1.e20;
    352:   lg->xmax  = -1.e20;
    353:   lg->ymax  = -1.e20;
    354:   lg->loc   = 0;
    355:   lg->nopts = 0;
    356:   return 0;
    357: }

    359: /*@
    360:    PetscDrawLGDestroy - Frees all space taken up by line graph data structure.

    362:    Collective on PetscDrawLG

    364:    Input Parameter:
    365: .  lg - the line graph context

    367:    Level: intermediate

    369: .seealso:  PetscDrawLGCreate()
    370: @*/
    371: PetscErrorCode  PetscDrawLGDestroy(PetscDrawLG *lg)
    372: {
    373:   PetscInt       i;

    375:   if (!*lg) return 0;
    377:   if (--((PetscObject)(*lg))->refct > 0) {*lg = NULL; return 0;}

    379:   if ((*lg)->legend) {
    380:     for (i=0; i<(*lg)->dim; i++) {
    381:       PetscFree((*lg)->legend[i]);
    382:     }
    383:     PetscFree((*lg)->legend);
    384:   }
    385:   PetscFree((*lg)->colors);
    386:   PetscFree2((*lg)->x,(*lg)->y);
    387:   PetscDrawAxisDestroy(&(*lg)->axis);
    388:   PetscDrawDestroy(&(*lg)->win);
    389:   PetscHeaderDestroy(lg);
    390:   return 0;
    391: }
    392: /*@
    393:    PetscDrawLGSetUseMarkers - Causes LG to draw a marker for each data-point.

    395:    Logically Collective on PetscDrawLG

    397:    Input Parameters:
    398: +  lg - the linegraph context
    399: -  flg - should mark each data point

    401:    Options Database:
    402: .  -lg_use_markers  <true,false> - true means the graphPetscDrawLG draws a marker for each point

    404:    Level: intermediate

    406: .seealso: PetscDrawLGCreate()
    407: @*/
    408: PetscErrorCode  PetscDrawLGSetUseMarkers(PetscDrawLG lg,PetscBool flg)
    409: {
    412:   lg->use_markers = flg;
    413:   return 0;
    414: }

    416: /*@
    417:    PetscDrawLGDraw - Redraws a line graph.

    419:    Collective on PetscDrawLG

    421:    Input Parameter:
    422: .  lg - the line graph context

    424:    Level: intermediate

    426: .seealso: PetscDrawSPDraw(), PetscDrawLGSPDraw(), PetscDrawLGReset()
    427: @*/
    428: PetscErrorCode  PetscDrawLGDraw(PetscDrawLG lg)
    429: {
    430:   PetscReal      xmin,xmax,ymin,ymax;
    431:   PetscMPIInt    rank;
    432:   PetscDraw      draw;
    433:   PetscBool      isnull;

    437:   PetscDrawIsNull(lg->win,&isnull);
    438:   if (isnull) return 0;
    439:   MPI_Comm_rank(PetscObjectComm((PetscObject)lg),&rank);

    441:   draw = lg->win;
    442:   PetscDrawCheckResizedWindow(draw);
    443:   PetscDrawClear(draw);

    445:   xmin = lg->xmin; xmax = lg->xmax; ymin = lg->ymin; ymax = lg->ymax;
    446:   PetscDrawAxisSetLimits(lg->axis,xmin,xmax,ymin,ymax);
    447:   PetscDrawAxisDraw(lg->axis);

    449:   PetscDrawCollectiveBegin(draw);
    450:   if (rank == 0) {
    451:     int i,j,dim=lg->dim,nopts=lg->nopts,cl;
    452:     for (i=0; i<dim; i++) {
    453:       for (j=1; j<nopts; j++) {
    454:         cl   = lg->colors ? lg->colors[i] : ((PETSC_DRAW_BLACK + i) % PETSC_DRAW_MAXCOLOR);
    455:         PetscDrawLine(draw,lg->x[(j-1)*dim+i],lg->y[(j-1)*dim+i],lg->x[j*dim+i],lg->y[j*dim+i],cl);
    456:         if (lg->use_markers) PetscDrawMarker(draw,lg->x[j*dim+i],lg->y[j*dim+i],cl);
    457:       }
    458:     }
    459:   }
    460:   if (rank == 0 && lg->legend) {
    461:     PetscBool right = PETSC_FALSE;
    462:     int       i,dim=lg->dim,cl;
    463:     PetscReal xl,yl,xr,yr,tw,th;
    464:     size_t    slen,len=0;
    465:     PetscDrawAxisGetLimits(lg->axis,&xl,&xr,&yl,&yr);
    466:     PetscDrawStringGetSize(draw,&tw,&th);
    467:     for (i=0; i<dim; i++) {
    468:       PetscStrlen(lg->legend[i],&slen);
    469:       len = PetscMax(len,slen);
    470:     }
    471:     if (right) {
    472:       xr = xr - 1.5*tw; xl = xr - (len + 7)*tw;
    473:     } else {
    474:       xl = xl + 1.5*tw; xr = xl + (len + 7)*tw;
    475:     }
    476:     yr = yr - 1.0*th; yl = yr - (dim + 1)*th;
    477:     PetscDrawLine(draw,xl,yl,xr,yl,PETSC_DRAW_BLACK);
    478:     PetscDrawLine(draw,xr,yl,xr,yr,PETSC_DRAW_BLACK);
    479:     PetscDrawLine(draw,xr,yr,xl,yr,PETSC_DRAW_BLACK);
    480:     PetscDrawLine(draw,xl,yr,xl,yl,PETSC_DRAW_BLACK);
    481:     for  (i=0; i<dim; i++) {
    482:       cl   = lg->colors ? lg->colors[i] : (PETSC_DRAW_BLACK + i);
    483:       PetscDrawLine(draw,xl + 1*tw,yr - (i + 1)*th,xl + 5*tw,yr - (i + 1)*th,cl);
    484:       PetscDrawString(draw,xl + 6*tw,yr - (i + 1.5)*th,PETSC_DRAW_BLACK,lg->legend[i]);
    485:     }
    486:   }
    487:   PetscDrawCollectiveEnd(draw);

    489:   PetscDrawFlush(draw);
    490:   PetscDrawPause(draw);
    491:   return 0;
    492: }

    494: /*@
    495:   PetscDrawLGSave - Saves a drawn image

    497:   Collective on PetscDrawLG

    499:   Input Parameter:
    500: . lg - The line graph context

    502:   Level: intermediate

    504: .seealso:  PetscDrawLGCreate(), PetscDrawLGGetDraw(), PetscDrawSetSave(), PetscDrawSave()
    505: @*/
    506: PetscErrorCode  PetscDrawLGSave(PetscDrawLG lg)
    507: {
    509:   PetscDrawSave(lg->win);
    510:   return 0;
    511: }

    513: /*@
    514:   PetscDrawLGView - Prints a line graph.

    516:   Collective on PetscDrawLG

    518:   Input Parameter:
    519: . lg - the line graph context

    521:   Level: beginner

    523: .seealso: PetscDrawLGCreate()

    525: @*/
    526: PetscErrorCode  PetscDrawLGView(PetscDrawLG lg,PetscViewer viewer)
    527: {
    528:   PetscReal      xmin=lg->xmin, xmax=lg->xmax, ymin=lg->ymin, ymax=lg->ymax;
    529:   PetscInt       i, j, dim = lg->dim, nopts = lg->nopts;

    533:   if (nopts < 1)                  return 0;
    534:   if (xmin > xmax || ymin > ymax) return 0;

    536:   if (!viewer) {
    537:     PetscViewerASCIIGetStdout(PetscObjectComm((PetscObject)lg),&viewer);
    538:   }
    539:   PetscObjectPrintClassNamePrefixType((PetscObject)lg,viewer);
    540:   for (i = 0; i < dim; i++) {
    541:     PetscViewerASCIIPrintf(viewer, "Line %" PetscInt_FMT ">\n", i);
    542:     for (j = 0; j < nopts; j++) {
    543:       PetscViewerASCIIPrintf(viewer, "  X: %g Y: %g\n", (double)lg->x[j*dim+i], (double)lg->y[j*dim+i]);
    544:     }
    545:   }
    546:   return 0;
    547: }

    549: /*@C
    550:    PetscDrawLGSetOptionsPrefix - Sets the prefix used for searching for all
    551:    PetscDrawLG options in the database.

    553:    Logically Collective on PetscDrawLG

    555:    Input Parameters:
    556: +  lg - the line graph context
    557: -  prefix - the prefix to prepend to all option names

    559:    Level: advanced

    561: .seealso: PetscDrawLGSetFromOptions(), PetscDrawLGCreate()
    562: @*/
    563: PetscErrorCode  PetscDrawLGSetOptionsPrefix(PetscDrawLG lg,const char prefix[])
    564: {
    566:   PetscObjectSetOptionsPrefix((PetscObject)lg,prefix);
    567:   return 0;
    568: }

    570: /*@
    571:     PetscDrawLGSetFromOptions - Sets options related to the PetscDrawLG

    573:     Collective on PetscDrawLG

    575:     Options Database:

    577:     Level: intermediate

    579: .seealso:  PetscDrawLGDestroy(), PetscDrawLGCreate()
    580: @*/
    581: PetscErrorCode  PetscDrawLGSetFromOptions(PetscDrawLG lg)
    582: {
    583:   PetscBool           usemarkers,set;
    584:   PetscDrawMarkerType markertype;

    588:   PetscDrawGetMarkerType(lg->win,&markertype);
    589:   PetscOptionsGetEnum(((PetscObject)lg)->options,((PetscObject)lg)->prefix,"-lg_marker_type",PetscDrawMarkerTypes,(PetscEnum*)&markertype,&set);
    590:   if (set) {
    591:     PetscDrawLGSetUseMarkers(lg,PETSC_TRUE);
    592:     PetscDrawSetMarkerType(lg->win,markertype);
    593:   }
    594:   usemarkers = lg->use_markers;
    595:   PetscOptionsGetBool(((PetscObject)lg)->options,((PetscObject)lg)->prefix,"-lg_use_markers",&usemarkers,&set);
    596:   if (set) PetscDrawLGSetUseMarkers(lg,usemarkers);
    597:   return 0;
    598: }