Date: 2022-03-04T17:37:03+00:00

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: {
     30:   *axis = lg->axis;
     31:   return(0);
     32: }

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

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

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

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

     45:    Level: intermediate

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

     58: /*@
     59:    PetscDrawLGSPDraw - Redraws a line graph.

     61:    Collective on PetscDrawLG

     63:    Input Parameter:
     64: .  lg - the line graph context

     66:    Level: intermediate

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

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

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

     86:   PetscDrawIsNull(lg->win,&isnull);
     87:   if (isnull) return(0);
     88:   MPI_Comm_rank(PetscObjectComm((PetscObject)lg),&rank);

     90:   draw = lg->win;
     91:   PetscDrawCheckResizedWindow(draw);
     92:   PetscDrawClear(draw);

     94:   xmin = PetscMin(lg->xmin,sp->xmin); ymin = PetscMin(lg->ymin,sp->ymin);
     95:   xmax = PetscMax(lg->xmax,sp->xmax); ymax = PetscMax(lg->ymax,sp->ymax);
     96:   PetscDrawAxisSetLimits(lg->axis,xmin,xmax,ymin,ymax);
     97:   PetscDrawAxisDraw(lg->axis);

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

    122:   PetscDrawFlush(draw);
    123:   PetscDrawPause(draw);
    124:   return(0);
    125: }

    127: /*@
    128:     PetscDrawLGCreate - Creates a line graph data structure.

    130:     Collective on PetscDraw

    132:     Input Parameters:
    133: +   draw - the window where the graph will be made.
    134: -   dim - the number of curves which will be drawn

    136:     Output Parameters:
    137: .   outlg - the line graph context

    139:     Level: intermediate

    141:     Notes:
    142:     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
    143:            zeroth MPI process in the communicator. All MPI processes in the communicator must call PetscDrawLGDraw() to display the updated graph.

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

    159:   PetscHeaderCreate(lg,PETSC_DRAWLG_CLASSID,"DrawLG","Line Graph","Draw",PetscObjectComm((PetscObject)draw),PetscDrawLGDestroy,NULL);
    160:   PetscLogObjectParent((PetscObject)draw,(PetscObject)lg);
    161:   PetscDrawLGSetOptionsPrefix(lg,((PetscObject)draw)->prefix);

    163:   PetscObjectReference((PetscObject)draw);
    164:   lg->win = draw;

    166:   lg->view    = NULL;
    167:   lg->destroy = NULL;
    168:   lg->nopts   = 0;
    169:   lg->dim     = dim;
    170:   lg->xmin    = 1.e20;
    171:   lg->ymin    = 1.e20;
    172:   lg->xmax    = -1.e20;
    173:   lg->ymax    = -1.e20;

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

    178:   lg->len         = dim*PETSC_DRAW_LG_CHUNK_SIZE;
    179:   lg->loc         = 0;
    180:   lg->use_markers = PETSC_FALSE;

    182:   PetscDrawAxisCreate(draw,&lg->axis);
    183:   PetscLogObjectParent((PetscObject)lg,(PetscObject)lg->axis);

    185:   *outlg = lg;
    186:   return(0);
    187: }

    189: /*@
    190:    PetscDrawLGSetColors - Sets the color of each line graph drawn

    192:    Logically Collective on PetscDrawLG

    194:    Input Parameters:
    195: +  lg - the line graph context.
    196: -  colors - the colors

    198:    Level: intermediate

    200: .seealso: PetscDrawLGCreate()

    202: @*/
    203: PetscErrorCode  PetscDrawLGSetColors(PetscDrawLG lg,const int colors[])
    204: {

    211:   PetscFree(lg->colors);
    212:   PetscMalloc1(lg->dim,&lg->colors);
    213:   PetscArraycpy(lg->colors,colors,lg->dim);
    214:   return(0);
    215: }

    217: /*@C
    218:    PetscDrawLGSetLegend - sets the names of each curve plotted

    220:    Logically Collective on PetscDrawLG

    222:    Input Parameters:
    223: +  lg - the line graph context.
    224: -  names - the names for each curve

    226:    Level: intermediate

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

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

    233: @*/
    234: PetscErrorCode  PetscDrawLGSetLegend(PetscDrawLG lg,const char *const *names)
    235: {
    237:   PetscInt       i;

    243:   if (lg->legend) {
    244:     for (i=0; i<lg->dim; i++) {
    245:       PetscFree(lg->legend[i]);
    246:     }
    247:     PetscFree(lg->legend);
    248:   }
    249:   if (names) {
    250:     PetscMalloc1(lg->dim,&lg->legend);
    251:     for (i=0; i<lg->dim; i++) {
    252:       PetscStrallocpy(names[i],&lg->legend[i]);
    253:     }
    254:   }
    255:   return(0);
    256: }

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

    261:    Not Collective

    263:    Input Parameter:
    264: .  lg - the line graph context.

    266:    Output Parameter:
    267: .  dim - the number of curves.

    269:    Level: intermediate

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

    273: @*/
    274: PetscErrorCode  PetscDrawLGGetDimension(PetscDrawLG lg,PetscInt *dim)
    275: {
    279:   *dim = lg->dim;
    280:   return(0);
    281: }

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

    286:    Logically Collective on PetscDrawLG

    288:    Input Parameters:
    289: +  lg - the line graph context.
    290: -  dim - the number of curves.

    292:    Level: intermediate

    294: .seealso: PetscDrawLGCreate(), PetscDrawLGGetDimension()
    295: @*/
    296: PetscErrorCode  PetscDrawLGSetDimension(PetscDrawLG lg,PetscInt dim)
    297: {
    299:   PetscInt       i;

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

    306:   PetscFree2(lg->x,lg->y);
    307:   if (lg->legend) {
    308:     for (i=0; i<lg->dim; i++) {
    309:       PetscFree(lg->legend[i]);
    310:     }
    311:     PetscFree(lg->legend);
    312:   }
    313:   PetscFree(lg->colors);
    314:   lg->dim = dim;
    315:   PetscMalloc2(dim*PETSC_DRAW_LG_CHUNK_SIZE,&lg->x,dim*PETSC_DRAW_LG_CHUNK_SIZE,&lg->y);
    316:   PetscLogObjectMemory((PetscObject)lg,2*dim*PETSC_DRAW_LG_CHUNK_SIZE*sizeof(PetscReal));
    317:   lg->len = dim*PETSC_DRAW_LG_CHUNK_SIZE;
    318:   return(0);
    319: }

    321: /*@
    322:    PetscDrawLGSetLimits - Sets the axis limits for a line graph. If more
    323:    points are added after this call, the limits will be adjusted to
    324:    include those additional points.

    326:    Logically Collective on PetscDrawLG

    328:    Input Parameters:
    329: +  xlg - the line graph context
    330: -  x_min,x_max,y_min,y_max - the limits

    332:    Level: intermediate

    334: .seealso: PetscDrawLGCreate()

    336: @*/
    337: PetscErrorCode  PetscDrawLGSetLimits(PetscDrawLG lg,PetscReal x_min,PetscReal x_max,PetscReal y_min,PetscReal y_max)
    338: {

    342:   (lg)->xmin = x_min;
    343:   (lg)->xmax = x_max;
    344:   (lg)->ymin = y_min;
    345:   (lg)->ymax = y_max;
    346:   return(0);
    347: }

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

    352:    Logically Collective on PetscDrawLG

    354:    Input Parameter:
    355: .  lg - the line graph context.

    357:    Level: intermediate

    359: .seealso: PetscDrawLGCreate()
    360: @*/
    361: PetscErrorCode  PetscDrawLGReset(PetscDrawLG lg)
    362: {
    365:   lg->xmin  = 1.e20;
    366:   lg->ymin  = 1.e20;
    367:   lg->xmax  = -1.e20;
    368:   lg->ymax  = -1.e20;
    369:   lg->loc   = 0;
    370:   lg->nopts = 0;
    371:   return(0);
    372: }

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

    377:    Collective on PetscDrawLG

    379:    Input Parameter:
    380: .  lg - the line graph context

    382:    Level: intermediate

    384: .seealso:  PetscDrawLGCreate()
    385: @*/
    386: PetscErrorCode  PetscDrawLGDestroy(PetscDrawLG *lg)
    387: {
    389:   PetscInt       i;

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

    396:   if ((*lg)->legend) {
    397:     for (i=0; i<(*lg)->dim; i++) {
    398:       PetscFree((*lg)->legend[i]);
    399:     }
    400:     PetscFree((*lg)->legend);
    401:   }
    402:   PetscFree((*lg)->colors);
    403:   PetscFree2((*lg)->x,(*lg)->y);
    404:   PetscDrawAxisDestroy(&(*lg)->axis);
    405:   PetscDrawDestroy(&(*lg)->win);
    406:   PetscHeaderDestroy(lg);
    407:   return(0);
    408: }
    409: /*@
    410:    PetscDrawLGSetUseMarkers - Causes LG to draw a marker for each data-point.

    412:    Logically Collective on PetscDrawLG

    414:    Input Parameters:
    415: +  lg - the linegraph context
    416: -  flg - should mark each data point

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

    421:    Level: intermediate

    423: .seealso: PetscDrawLGCreate()
    424: @*/
    425: PetscErrorCode  PetscDrawLGSetUseMarkers(PetscDrawLG lg,PetscBool flg)
    426: {
    430:   lg->use_markers = flg;
    431:   return(0);
    432: }

    434: /*@
    435:    PetscDrawLGDraw - Redraws a line graph.

    437:    Collective on PetscDrawLG

    439:    Input Parameter:
    440: .  lg - the line graph context

    442:    Level: intermediate

    444: .seealso: PetscDrawSPDraw(), PetscDrawLGSPDraw(), PetscDrawLGReset()
    445: @*/
    446: PetscErrorCode  PetscDrawLGDraw(PetscDrawLG lg)
    447: {
    448:   PetscReal      xmin,xmax,ymin,ymax;
    450:   PetscMPIInt    rank;
    451:   PetscDraw      draw;
    452:   PetscBool      isnull;

    456:   PetscDrawIsNull(lg->win,&isnull);
    457:   if (isnull) return(0);
    458:   MPI_Comm_rank(PetscObjectComm((PetscObject)lg),&rank);

    460:   draw = lg->win;
    461:   PetscDrawCheckResizedWindow(draw);
    462:   PetscDrawClear(draw);

    464:   xmin = lg->xmin; xmax = lg->xmax; ymin = lg->ymin; ymax = lg->ymax;
    465:   PetscDrawAxisSetLimits(lg->axis,xmin,xmax,ymin,ymax);
    466:   PetscDrawAxisDraw(lg->axis);

    468:   PetscDrawCollectiveBegin(draw);
    469:   if (rank == 0) {
    470:     int i,j,dim=lg->dim,nopts=lg->nopts,cl;
    471:     for (i=0; i<dim; i++) {
    472:       for (j=1; j<nopts; j++) {
    473:         cl   = lg->colors ? lg->colors[i] : ((PETSC_DRAW_BLACK + i) % PETSC_DRAW_MAXCOLOR);
    474:         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);
    475:         if (lg->use_markers) {PetscDrawMarker(draw,lg->x[j*dim+i],lg->y[j*dim+i],cl);}
    476:       }
    477:     }
    478:   }
    479:   if (rank == 0 && lg->legend) {
    480:     int       i,dim=lg->dim,cl;
    481:     PetscReal xl,yl,xr,yr,tw,th;
    482:     size_t    slen,len=0;
    483:     PetscDrawAxisGetLimits(lg->axis,&xl,&xr,&yl,&yr);
    484:     PetscDrawStringGetSize(draw,&tw,&th);
    485:     for (i=0; i<dim; i++) {
    486:       PetscStrlen(lg->legend[i],&slen);
    487:       len = PetscMax(len,slen);
    488:     }
    489:     xr = xr - 1.5*tw; xl = xr - (len + 7)*tw;
    490:     yr = yr - 1.0*th; yl = yr - (dim + 1)*th;
    491:     PetscDrawLine(draw,xl,yl,xr,yl,PETSC_DRAW_BLACK);
    492:     PetscDrawLine(draw,xr,yl,xr,yr,PETSC_DRAW_BLACK);
    493:     PetscDrawLine(draw,xr,yr,xl,yr,PETSC_DRAW_BLACK);
    494:     PetscDrawLine(draw,xl,yr,xl,yl,PETSC_DRAW_BLACK);
    495:     for  (i=0; i<dim; i++) {
    496:       cl   = lg->colors ? lg->colors[i] : (PETSC_DRAW_BLACK + i);
    497:       PetscDrawLine(draw,xl + 1*tw,yr - (i + 1)*th,xl + 5*tw,yr - (i + 1)*th,cl);
    498:       PetscDrawString(draw,xl + 6*tw,yr - (i + 1.5)*th,PETSC_DRAW_BLACK,lg->legend[i]);
    499:     }
    500:   }
    501:   PetscDrawCollectiveEnd(draw);

    503:   PetscDrawFlush(draw);
    504:   PetscDrawPause(draw);
    505:   return(0);
    506: }

    508: /*@
    509:   PetscDrawLGSave - Saves a drawn image

    511:   Collective on PetscDrawLG

    513:   Input Parameter:
    514: . lg - The line graph context

    516:   Level: intermediate

    518: .seealso:  PetscDrawLGCreate(), PetscDrawLGGetDraw(), PetscDrawSetSave(), PetscDrawSave()
    519: @*/
    520: PetscErrorCode  PetscDrawLGSave(PetscDrawLG lg)
    521: {

    526:   PetscDrawSave(lg->win);
    527:   return(0);
    528: }

    530: /*@
    531:   PetscDrawLGView - Prints a line graph.

    533:   Collective on PetscDrawLG

    535:   Input Parameter:
    536: . lg - the line graph context

    538:   Level: beginner

    540: .seealso: PetscDrawLGCreate()

    542: @*/
    543: PetscErrorCode  PetscDrawLGView(PetscDrawLG lg,PetscViewer viewer)
    544: {
    545:   PetscReal      xmin=lg->xmin, xmax=lg->xmax, ymin=lg->ymin, ymax=lg->ymax;
    546:   PetscInt       i, j, dim = lg->dim, nopts = lg->nopts;

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

    555:   if (!viewer) {
    556:     PetscViewerASCIIGetStdout(PetscObjectComm((PetscObject)lg),&viewer);
    557:   }
    558:   PetscObjectPrintClassNamePrefixType((PetscObject)lg,viewer);
    559:   for (i = 0; i < dim; i++) {
    560:     PetscViewerASCIIPrintf(viewer, "Line %D>\n", i);
    561:     for (j = 0; j < nopts; j++) {
    562:       PetscViewerASCIIPrintf(viewer, "  X: %g Y: %g\n", (double)lg->x[j*dim+i], (double)lg->y[j*dim+i]);
    563:     }
    564:   }
    565:   return(0);
    566: }

    568: /*@C
    569:    PetscDrawLGSetOptionsPrefix - Sets the prefix used for searching for all
    570:    PetscDrawLG options in the database.

    572:    Logically Collective on PetscDrawLG

    574:    Input Parameters:
    575: +  lg - the line graph context
    576: -  prefix - the prefix to prepend to all option names

    578:    Level: advanced

    580: .seealso: PetscDrawLGSetFromOptions(), PetscDrawLGCreate()
    581: @*/
    582: PetscErrorCode  PetscDrawLGSetOptionsPrefix(PetscDrawLG lg,const char prefix[])
    583: {

    588:   PetscObjectSetOptionsPrefix((PetscObject)lg,prefix);
    589:   return(0);
    590: }

    592: /*@
    593:     PetscDrawLGSetFromOptions - Sets options related to the PetscDrawLG

    595:     Collective on PetscDrawLG

    597:     Options Database:

    599:     Level: intermediate

    601: .seealso:  PetscDrawLGDestroy(), PetscDrawLGCreate()
    602: @*/
    603: PetscErrorCode  PetscDrawLGSetFromOptions(PetscDrawLG lg)
    604: {
    605:   PetscErrorCode      ierr;
    606:   PetscBool           usemarkers,set;
    607:   PetscDrawMarkerType markertype;

    612:   PetscDrawGetMarkerType(lg->win,&markertype);
    613:   PetscOptionsGetEnum(((PetscObject)lg)->options,((PetscObject)lg)->prefix,"-lg_marker_type",PetscDrawMarkerTypes,(PetscEnum*)&markertype,&set);
    614:   if (set) {
    615:     PetscDrawLGSetUseMarkers(lg,PETSC_TRUE);
    616:     PetscDrawSetMarkerType(lg->win,markertype);
    617:   }
    618:   usemarkers = lg->use_markers;
    619:   PetscOptionsGetBool(((PetscObject)lg)->options,((PetscObject)lg)->prefix,"-lg_use_markers",&usemarkers,&set);
    620:   if (set) {PetscDrawLGSetUseMarkers(lg,usemarkers);}
    621:   return(0);
    622: }