Date: 2021-09-20T09:43:50+00:00

Actual source code: epsmon.c
slepc-3.15.2 2021-09-20
Report Typos and Errors

      1: /*
      2:    - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
      3:    SLEPc - Scalable Library for Eigenvalue Problem Computations
      4:    Copyright (c) 2002-2021, Universitat Politecnica de Valencia, Spain

      6:    This file is part of SLEPc.
      7:    SLEPc is distributed under a 2-clause BSD license (see LICENSE).
      8:    - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
      9: */
     10: /*
     11:    EPS routines related to monitors
     12: */

     14: #include <slepc/private/epsimpl.h>
     15: #include <petscdraw.h>

     17: PetscErrorCode EPSMonitorLGCreate(MPI_Comm comm,const char host[],const char label[],const char metric[],PetscInt l,const char *names[],int x,int y,int m,int n,PetscDrawLG *lgctx)
     18: {
     19:   PetscDraw      draw;
     20:   PetscDrawAxis  axis;
     21:   PetscDrawLG    lg;

     25:   PetscDrawCreate(comm,host,label,x,y,m,n,&draw);
     26:   PetscDrawSetFromOptions(draw);
     27:   PetscDrawLGCreate(draw,l,&lg);
     28:   if (names) { PetscDrawLGSetLegend(lg,names); }
     29:   PetscDrawLGSetFromOptions(lg);
     30:   PetscDrawLGGetAxis(lg,&axis);
     31:   PetscDrawAxisSetLabels(axis,"Convergence","Iteration",metric);
     32:   PetscDrawDestroy(&draw);
     33:   *lgctx = lg;
     34:   return(0);
     35: }

     37: /*
     38:    Runs the user provided monitor routines, if any.
     39: */
     40: PetscErrorCode EPSMonitor(EPS eps,PetscInt it,PetscInt nconv,PetscScalar *eigr,PetscScalar *eigi,PetscReal *errest,PetscInt nest)
     41: {
     43:   PetscInt       i,n = eps->numbermonitors;

     46:   for (i=0;i<n;i++) {
     47:     (*eps->monitor[i])(eps,it,nconv,eigr,eigi,errest,nest,eps->monitorcontext[i]);
     48:   }
     49:   return(0);
     50: }

     52: /*@C
     53:    EPSMonitorSet - Sets an ADDITIONAL function to be called at every
     54:    iteration to monitor the error estimates for each requested eigenpair.

     56:    Logically Collective on eps

     58:    Input Parameters:
     59: +  eps     - eigensolver context obtained from EPSCreate()
     60: .  monitor - pointer to function (if this is NULL, it turns off monitoring)
     61: .  mctx    - [optional] context for private data for the
     62:              monitor routine (use NULL if no context is desired)
     63: -  monitordestroy - [optional] routine that frees monitor context (may be NULL)

     65:    Calling Sequence of monitor:
     66: $   monitor(EPS eps,int its,int nconv,PetscScalar *eigr,PetscScalar *eigi,PetscReal* errest,int nest,void *mctx)

     68: +  eps    - eigensolver context obtained from EPSCreate()
     69: .  its    - iteration number
     70: .  nconv  - number of converged eigenpairs
     71: .  eigr   - real part of the eigenvalues
     72: .  eigi   - imaginary part of the eigenvalues
     73: .  errest - relative error estimates for each eigenpair
     74: .  nest   - number of error estimates
     75: -  mctx   - optional monitoring context, as set by EPSMonitorSet()

     77:    Options Database Keys:
     78: +    -eps_monitor        - print only the first error estimate
     79: .    -eps_monitor_all    - print error estimates at each iteration
     80: .    -eps_monitor_conv   - print the eigenvalue approximations only when
     81:       convergence has been reached
     82: .    -eps_monitor draw::draw_lg - sets line graph monitor for the first unconverged
     83:       approximate eigenvalue
     84: .    -eps_monitor_all draw::draw_lg - sets line graph monitor for all unconverged
     85:       approximate eigenvalues
     86: .    -eps_monitor_conv draw::draw_lg - sets line graph monitor for convergence history
     87: -    -eps_monitor_cancel - cancels all monitors that have been hardwired into
     88:       a code by calls to EPSMonitorSet(), but does not cancel those set via
     89:       the options database.

     91:    Notes:
     92:    Several different monitoring routines may be set by calling
     93:    EPSMonitorSet() multiple times; all will be called in the
     94:    order in which they were set.

     96:    Level: intermediate

     98: .seealso: EPSMonitorFirst(), EPSMonitorAll(), EPSMonitorCancel()
     99: @*/
    100: PetscErrorCode EPSMonitorSet(EPS eps,PetscErrorCode (*monitor)(EPS,PetscInt,PetscInt,PetscScalar*,PetscScalar*,PetscReal*,PetscInt,void*),void *mctx,PetscErrorCode (*monitordestroy)(void**))
    101: {
    104:   if (eps->numbermonitors >= MAXEPSMONITORS) SETERRQ(PetscObjectComm((PetscObject)eps),PETSC_ERR_ARG_OUTOFRANGE,"Too many EPS monitors set");
    105:   eps->monitor[eps->numbermonitors]           = monitor;
    106:   eps->monitorcontext[eps->numbermonitors]    = (void*)mctx;
    107:   eps->monitordestroy[eps->numbermonitors++]  = monitordestroy;
    108:   return(0);
    109: }

    111: /*@
    112:    EPSMonitorCancel - Clears all monitors for an EPS object.

    114:    Logically Collective on eps

    116:    Input Parameters:
    117: .  eps - eigensolver context obtained from EPSCreate()

    119:    Options Database Key:
    120: .    -eps_monitor_cancel - Cancels all monitors that have been hardwired
    121:       into a code by calls to EPSMonitorSet(),
    122:       but does not cancel those set via the options database.

    124:    Level: intermediate

    126: .seealso: EPSMonitorSet()
    127: @*/
    128: PetscErrorCode EPSMonitorCancel(EPS eps)
    129: {
    131:   PetscInt       i;

    135:   for (i=0; i<eps->numbermonitors; i++) {
    136:     if (eps->monitordestroy[i]) {
    137:       (*eps->monitordestroy[i])(&eps->monitorcontext[i]);
    138:     }
    139:   }
    140:   eps->numbermonitors = 0;
    141:   return(0);
    142: }

    144: /*@C
    145:    EPSGetMonitorContext - Gets the monitor context, as set by
    146:    EPSMonitorSet() for the FIRST monitor only.

    148:    Not Collective

    150:    Input Parameter:
    151: .  eps - eigensolver context obtained from EPSCreate()

    153:    Output Parameter:
    154: .  ctx - monitor context

    156:    Level: intermediate

    158: .seealso: EPSMonitorSet()
    159: @*/
    160: PetscErrorCode EPSGetMonitorContext(EPS eps,void **ctx)
    161: {
    164:   *ctx = eps->monitorcontext[0];
    165:   return(0);
    166: }

    168: /*@C
    169:    EPSMonitorFirst - Print the first unconverged approximate value and
    170:    error estimate at each iteration of the eigensolver.

    172:    Collective on eps

    174:    Input Parameters:
    175: +  eps    - eigensolver context
    176: .  its    - iteration number
    177: .  nconv  - number of converged eigenpairs so far
    178: .  eigr   - real part of the eigenvalues
    179: .  eigi   - imaginary part of the eigenvalues
    180: .  errest - error estimates
    181: .  nest   - number of error estimates to display
    182: -  vf     - viewer and format for monitoring

    184:    Options Database Key:
    185: .  -eps_monitor - activates EPSMonitorFirst()

    187:    Level: intermediate

    189: .seealso: EPSMonitorSet(), EPSMonitorAll(), EPSMonitorConverged()
    190: @*/
    191: PetscErrorCode EPSMonitorFirst(EPS eps,PetscInt its,PetscInt nconv,PetscScalar *eigr,PetscScalar *eigi,PetscReal *errest,PetscInt nest,PetscViewerAndFormat *vf)
    192: {
    194:   PetscScalar    er,ei;
    195:   PetscViewer    viewer;

    200:   viewer = vf->viewer;
    202:   if (its==1 && ((PetscObject)eps)->prefix) {
    203:     PetscViewerASCIIPrintf(viewer,"  Eigenvalue approximations and residual norms for %s solve.\n",((PetscObject)eps)->prefix);
    204:   }
    205:   if (nconv<nest) {
    206:     PetscViewerPushFormat(viewer,vf->format);
    207:     PetscViewerASCIIAddTab(viewer,((PetscObject)eps)->tablevel);
    208:     PetscViewerASCIIPrintf(viewer,"%3D EPS nconv=%D first unconverged value (error)",its,nconv);
    209:     PetscViewerASCIIUseTabs(viewer,PETSC_FALSE);
    210:     er = eigr[nconv]; ei = eigi[nconv];
    211:     STBackTransform(eps->st,1,&er,&ei);
    212: #if defined(PETSC_USE_COMPLEX)
    213:     PetscViewerASCIIPrintf(viewer," %g%+gi",(double)PetscRealPart(er),(double)PetscImaginaryPart(er));
    214: #else
    215:     PetscViewerASCIIPrintf(viewer," %g",(double)er);
    216:     if (ei!=0.0) { PetscViewerASCIIPrintf(viewer,"%+gi",(double)ei); }
    217: #endif
    218:     PetscViewerASCIIPrintf(viewer," (%10.8e)\n",(double)errest[nconv]);
    219:     PetscViewerASCIIUseTabs(viewer,PETSC_TRUE);
    220:     PetscViewerASCIISubtractTab(viewer,((PetscObject)eps)->tablevel);
    221:     PetscViewerPopFormat(viewer);
    222:   }
    223:   return(0);
    224: }

    226: /*@C
    227:    EPSMonitorAll - Print the current approximate values and
    228:    error estimates at each iteration of the eigensolver.

    230:    Collective on eps

    232:    Input Parameters:
    233: +  eps    - eigensolver context
    234: .  its    - iteration number
    235: .  nconv  - number of converged eigenpairs so far
    236: .  eigr   - real part of the eigenvalues
    237: .  eigi   - imaginary part of the eigenvalues
    238: .  errest - error estimates
    239: .  nest   - number of error estimates to display
    240: -  vf     - viewer and format for monitoring

    242:    Options Database Key:
    243: .  -eps_monitor_all - activates EPSMonitorAll()

    245:    Level: intermediate

    247: .seealso: EPSMonitorSet(), EPSMonitorFirst(), EPSMonitorConverged()
    248: @*/
    249: PetscErrorCode EPSMonitorAll(EPS eps,PetscInt its,PetscInt nconv,PetscScalar *eigr,PetscScalar *eigi,PetscReal *errest,PetscInt nest,PetscViewerAndFormat *vf)
    250: {
    252:   PetscInt       i;
    253:   PetscScalar    er,ei;
    254:   PetscViewer    viewer;

    259:   viewer = vf->viewer;
    261:   PetscViewerPushFormat(viewer,vf->format);
    262:   PetscViewerASCIIAddTab(viewer,((PetscObject)eps)->tablevel);
    263:   if (its==1 && ((PetscObject)eps)->prefix) {
    264:     PetscViewerASCIIPrintf(viewer,"  Eigenvalue approximations and residual norms for %s solve.\n",((PetscObject)eps)->prefix);
    265:   }
    266:   PetscViewerASCIIPrintf(viewer,"%3D EPS nconv=%D Values (Errors)",its,nconv);
    267:   PetscViewerASCIIUseTabs(viewer,PETSC_FALSE);
    268:   for (i=0;i<nest;i++) {
    269:     er = eigr[i]; ei = eigi[i];
    270:     STBackTransform(eps->st,1,&er,&ei);
    271: #if defined(PETSC_USE_COMPLEX)
    272:     PetscViewerASCIIPrintf(viewer," %g%+gi",(double)PetscRealPart(er),(double)PetscImaginaryPart(er));
    273: #else
    274:     PetscViewerASCIIPrintf(viewer," %g",(double)er);
    275:     if (ei!=0.0) { PetscViewerASCIIPrintf(viewer,"%+gi",(double)ei); }
    276: #endif
    277:     PetscViewerASCIIPrintf(viewer," (%10.8e)",(double)errest[i]);
    278:   }
    279:   PetscViewerASCIIPrintf(viewer,"\n");
    280:   PetscViewerASCIIUseTabs(viewer,PETSC_TRUE);
    281:   PetscViewerASCIISubtractTab(viewer,((PetscObject)eps)->tablevel);
    282:   PetscViewerPopFormat(viewer);
    283:   return(0);
    284: }

    286: /*@C
    287:    EPSMonitorConverged - Print the approximate values and
    288:    error estimates as they converge.

    290:    Collective on eps

    292:    Input Parameters:
    293: +  eps    - eigensolver context
    294: .  its    - iteration number
    295: .  nconv  - number of converged eigenpairs so far
    296: .  eigr   - real part of the eigenvalues
    297: .  eigi   - imaginary part of the eigenvalues
    298: .  errest - error estimates
    299: .  nest   - number of error estimates to display
    300: -  vf     - viewer and format for monitoring

    302:    Options Database Key:
    303: .  -eps_monitor_conv - activates EPSMonitorConverged()

    305:    Level: intermediate

    307: .seealso: EPSMonitorSet(), EPSMonitorFirst(), EPSMonitorAll()
    308: @*/
    309: PetscErrorCode EPSMonitorConverged(EPS eps,PetscInt its,PetscInt nconv,PetscScalar *eigr,PetscScalar *eigi,PetscReal *errest,PetscInt nest,PetscViewerAndFormat *vf)
    310: {
    312:   PetscInt       i;
    313:   PetscScalar    er,ei;
    314:   PetscViewer    viewer;
    315:   SlepcConvMon   ctx;

    320:   viewer = vf->viewer;
    322:   ctx = (SlepcConvMon)vf->data;
    323:   if (its==1 && ((PetscObject)eps)->prefix) {
    324:     PetscViewerASCIIPrintf(viewer,"  Convergence history for %s solve.\n",((PetscObject)eps)->prefix);
    325:   }
    326:   if (its==1) ctx->oldnconv = 0;
    327:   if (ctx->oldnconv!=nconv) {
    328:     PetscViewerPushFormat(viewer,vf->format);
    329:     PetscViewerASCIIAddTab(viewer,((PetscObject)eps)->tablevel);
    330:     for (i=ctx->oldnconv;i<nconv;i++) {
    331:       PetscViewerASCIIPrintf(viewer,"%3D EPS converged value (error) #%D",its,i);
    332:       PetscViewerASCIIUseTabs(viewer,PETSC_FALSE);
    333:       er = eigr[i]; ei = eigi[i];
    334:       STBackTransform(eps->st,1,&er,&ei);
    335: #if defined(PETSC_USE_COMPLEX)
    336:       PetscViewerASCIIPrintf(viewer," %g%+gi",(double)PetscRealPart(er),(double)PetscImaginaryPart(er));
    337: #else
    338:       PetscViewerASCIIPrintf(viewer," %g",(double)er);
    339:       if (ei!=0.0) { PetscViewerASCIIPrintf(viewer,"%+gi",(double)ei); }
    340: #endif
    341:       PetscViewerASCIIPrintf(viewer," (%10.8e)\n",(double)errest[i]);
    342:       PetscViewerASCIIUseTabs(viewer,PETSC_TRUE);
    343:     }
    344:     PetscViewerASCIISubtractTab(viewer,((PetscObject)eps)->tablevel);
    345:     PetscViewerPopFormat(viewer);
    346:     ctx->oldnconv = nconv;
    347:   }
    348:   return(0);
    349: }

    351: PetscErrorCode EPSMonitorConvergedCreate(PetscViewer viewer,PetscViewerFormat format,void *ctx,PetscViewerAndFormat **vf)
    352: {
    354:   SlepcConvMon   mctx;

    357:   PetscViewerAndFormatCreate(viewer,format,vf);
    358:   PetscNew(&mctx);
    359:   mctx->ctx = ctx;
    360:   (*vf)->data = (void*)mctx;
    361:   return(0);
    362: }

    364: PetscErrorCode EPSMonitorConvergedDestroy(PetscViewerAndFormat **vf)
    365: {

    369:   if (!*vf) return(0);
    370:   PetscFree((*vf)->data);
    371:   PetscViewerDestroy(&(*vf)->viewer);
    372:   PetscDrawLGDestroy(&(*vf)->lg);
    373:   PetscFree(*vf);
    374:   return(0);
    375: }

    377: /*@C
    378:    EPSMonitorFirstDrawLG - Plots the error estimate of the first unconverged
    379:    approximation at each iteration of the eigensolver.

    381:    Collective on eps

    383:    Input Parameters:
    384: +  eps    - eigensolver context
    385: .  its    - iteration number
    386: .  its    - iteration number
    387: .  nconv  - number of converged eigenpairs so far
    388: .  eigr   - real part of the eigenvalues
    389: .  eigi   - imaginary part of the eigenvalues
    390: .  errest - error estimates
    391: .  nest   - number of error estimates to display
    392: -  vf     - viewer and format for monitoring

    394:    Options Database Key:
    395: .  -eps_monitor draw::draw_lg - activates EPSMonitorFirstDrawLG()

    397:    Level: intermediate

    399: .seealso: EPSMonitorSet()
    400: @*/
    401: PetscErrorCode EPSMonitorFirstDrawLG(EPS eps,PetscInt its,PetscInt nconv,PetscScalar *eigr,PetscScalar *eigi,PetscReal *errest,PetscInt nest,PetscViewerAndFormat *vf)
    402: {
    404:   PetscViewer    viewer;
    405:   PetscDrawLG    lg;
    406:   PetscReal      x,y;

    411:   viewer = vf->viewer;
    413:   lg = vf->lg;
    415:   PetscViewerPushFormat(viewer,vf->format);
    416:   if (its==1) {
    417:     PetscDrawLGReset(lg);
    418:     PetscDrawLGSetDimension(lg,1);
    419:     PetscDrawLGSetLimits(lg,1,1,PetscLog10Real(eps->tol)-2,0.0);
    420:   }
    421:   if (nconv<nest) {
    422:     x = (PetscReal)its;
    423:     if (errest[nconv] > 0.0) y = PetscLog10Real(errest[nconv]);
    424:     else y = 0.0;
    425:     PetscDrawLGAddPoint(lg,&x,&y);
    426:     if (its <= 20 || !(its % 5) || eps->reason) {
    427:       PetscDrawLGDraw(lg);
    428:       PetscDrawLGSave(lg);
    429:     }
    430:   }
    431:   PetscViewerPopFormat(viewer);
    432:   return(0);
    433: }

    435: /*@C
    436:    EPSMonitorFirstDrawLGCreate - Creates the plotter for the first error estimate.

    438:    Collective on viewer

    440:    Input Parameters:
    441: +  viewer - the viewer
    442: .  format - the viewer format
    443: -  ctx    - an optional user context

    445:    Output Parameter:
    446: .  vf     - the viewer and format context

    448:    Level: intermediate

    450: .seealso: EPSMonitorSet()
    451: @*/
    452: PetscErrorCode EPSMonitorFirstDrawLGCreate(PetscViewer viewer,PetscViewerFormat format,void *ctx,PetscViewerAndFormat **vf)
    453: {

    457:   PetscViewerAndFormatCreate(viewer,format,vf);
    458:   (*vf)->data = ctx;
    459:   EPSMonitorLGCreate(PetscObjectComm((PetscObject)viewer),NULL,"First Error Estimate","Log Error Estimate",1,NULL,PETSC_DECIDE,PETSC_DECIDE,400,300,&(*vf)->lg);
    460:   return(0);
    461: }

    463: /*@C
    464:    EPSMonitorAllDrawLG - Plots the error estimate of all unconverged
    465:    approximations at each iteration of the eigensolver.

    467:    Collective on eps

    469:    Input Parameters:
    470: +  eps    - eigensolver context
    471: .  its    - iteration number
    472: .  its    - iteration number
    473: .  nconv  - number of converged eigenpairs so far
    474: .  eigr   - real part of the eigenvalues
    475: .  eigi   - imaginary part of the eigenvalues
    476: .  errest - error estimates
    477: .  nest   - number of error estimates to display
    478: -  vf     - viewer and format for monitoring

    480:    Options Database Key:
    481: .  -eps_monitor_all draw::draw_lg - activates EPSMonitorAllDrawLG()

    483:    Level: intermediate

    485: .seealso: EPSMonitorSet()
    486: @*/
    487: PetscErrorCode EPSMonitorAllDrawLG(EPS eps,PetscInt its,PetscInt nconv,PetscScalar *eigr,PetscScalar *eigi,PetscReal *errest,PetscInt nest,PetscViewerAndFormat *vf)
    488: {
    490:   PetscViewer    viewer;
    491:   PetscDrawLG    lg;
    492:   PetscInt       i,n = PetscMin(eps->nev,255);
    493:   PetscReal      *x,*y;

    498:   viewer = vf->viewer;
    500:   lg = vf->lg;
    502:   PetscViewerPushFormat(viewer,vf->format);
    503:   if (its==1) {
    504:     PetscDrawLGReset(lg);
    505:     PetscDrawLGSetDimension(lg,n);
    506:     PetscDrawLGSetLimits(lg,1,1,PetscLog10Real(eps->tol)-2,0.0);
    507:   }
    508:   PetscMalloc2(n,&x,n,&y);
    509:   for (i=0;i<n;i++) {
    510:     x[i] = (PetscReal)its;
    511:     if (i < nest && errest[i] > 0.0) y[i] = PetscLog10Real(errest[i]);
    512:     else y[i] = 0.0;
    513:   }
    514:   PetscDrawLGAddPoint(lg,x,y);
    515:   if (its <= 20 || !(its % 5) || eps->reason) {
    516:     PetscDrawLGDraw(lg);
    517:     PetscDrawLGSave(lg);
    518:   }
    519:   PetscFree2(x,y);
    520:   PetscViewerPopFormat(viewer);
    521:   return(0);
    522: }

    524: /*@C
    525:    EPSMonitorAllDrawLGCreate - Creates the plotter for all the error estimates.

    527:    Collective on viewer

    529:    Input Parameters:
    530: +  viewer - the viewer
    531: .  format - the viewer format
    532: -  ctx    - an optional user context

    534:    Output Parameter:
    535: .  vf     - the viewer and format context

    537:    Level: intermediate

    539: .seealso: EPSMonitorSet()
    540: @*/
    541: PetscErrorCode EPSMonitorAllDrawLGCreate(PetscViewer viewer,PetscViewerFormat format,void *ctx,PetscViewerAndFormat **vf)
    542: {

    546:   PetscViewerAndFormatCreate(viewer,format,vf);
    547:   (*vf)->data = ctx;
    548:   EPSMonitorLGCreate(PetscObjectComm((PetscObject)viewer),NULL,"All Error Estimates","Log Error Estimate",1,NULL,PETSC_DECIDE,PETSC_DECIDE,400,300,&(*vf)->lg);
    549:   return(0);
    550: }

    552: /*@C
    553:    EPSMonitorConvergedDrawLG - Plots the number of converged eigenvalues
    554:    at each iteration of the eigensolver.

    556:    Collective on eps

    558:    Input Parameters:
    559: +  eps    - eigensolver context
    560: .  its    - iteration number
    561: .  its    - iteration number
    562: .  nconv  - number of converged eigenpairs so far
    563: .  eigr   - real part of the eigenvalues
    564: .  eigi   - imaginary part of the eigenvalues
    565: .  errest - error estimates
    566: .  nest   - number of error estimates to display
    567: -  vf     - viewer and format for monitoring

    569:    Options Database Key:
    570: .  -eps_monitor_conv draw::draw_lg - activates EPSMonitorConvergedDrawLG()

    572:    Level: intermediate

    574: .seealso: EPSMonitorSet()
    575: @*/
    576: PetscErrorCode EPSMonitorConvergedDrawLG(EPS eps,PetscInt its,PetscInt nconv,PetscScalar *eigr,PetscScalar *eigi,PetscReal *errest,PetscInt nest,PetscViewerAndFormat *vf)
    577: {
    578:   PetscErrorCode   ierr;
    579:   PetscViewer      viewer;
    580:   PetscDrawLG      lg;
    581:   PetscReal        x,y;

    586:   viewer = vf->viewer;
    588:   lg = vf->lg;
    590:   PetscViewerPushFormat(viewer,vf->format);
    591:   if (its==1) {
    592:     PetscDrawLGReset(lg);
    593:     PetscDrawLGSetDimension(lg,1);
    594:     PetscDrawLGSetLimits(lg,1,1,0,eps->nev);
    595:   }
    596:   x = (PetscReal)its;
    597:   y = (PetscReal)eps->nconv;
    598:   PetscDrawLGAddPoint(lg,&x,&y);
    599:   if (its <= 20 || !(its % 5) || eps->reason) {
    600:     PetscDrawLGDraw(lg);
    601:     PetscDrawLGSave(lg);
    602:   }
    603:   PetscViewerPopFormat(viewer);
    604:   return(0);
    605: }

    607: /*@C
    608:    EPSMonitorConvergedDrawLGCreate - Creates the plotter for the convergence history.

    610:    Collective on viewer

    612:    Input Parameters:
    613: +  viewer - the viewer
    614: .  format - the viewer format
    615: -  ctx    - an optional user context

    617:    Output Parameter:
    618: .  vf     - the viewer and format context

    620:    Level: intermediate

    622: .seealso: EPSMonitorSet()
    623: @*/
    624: PetscErrorCode EPSMonitorConvergedDrawLGCreate(PetscViewer viewer,PetscViewerFormat format,void *ctx,PetscViewerAndFormat **vf)
    625: {
    627:   SlepcConvMon   mctx;

    630:   PetscViewerAndFormatCreate(viewer,format,vf);
    631:   PetscNew(&mctx);
    632:   mctx->ctx = ctx;
    633:   (*vf)->data = (void*)mctx;
    634:   EPSMonitorLGCreate(PetscObjectComm((PetscObject)viewer),NULL,"Convergence History","Number Converged",1,NULL,PETSC_DECIDE,PETSC_DECIDE,400,300,&(*vf)->lg);
    635:   return(0);
    636: }