Actual source code: epsmon.c
slepc-3.21.1 2024-04-26
Report Typos and Errors

      1: /*
      2:    - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
      3:    SLEPc - Scalable Library for Eigenvalue Problem Computations
      4:    Copyright (c) 2002-, 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;

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

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

     43:   PetscFunctionBegin;
     44:   for (i=0;i<n;i++) PetscCall((*eps->monitor[i])(eps,it,nconv,eigr,eigi,errest,nest,eps->monitorcontext[i]));
     45:   PetscFunctionReturn(PETSC_SUCCESS);
     46: }

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

     52:    Logically Collective

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

     61:    Calling sequence of monitor:
     62: $  PetscErrorCode monitor(EPS eps,PetscInt its,PetscInt nconv,PetscScalar *eigr,PetscScalar *eigi,PetscReal *errest,PetscInt nest,void *mctx)
     63: +  eps    - eigensolver context obtained from EPSCreate()
     64: .  its    - iteration number
     65: .  nconv  - number of converged eigenpairs
     66: .  eigr   - real part of the eigenvalues
     67: .  eigi   - imaginary part of the eigenvalues
     68: .  errest - relative error estimates for each eigenpair
     69: .  nest   - number of error estimates
     70: -  mctx   - optional monitoring context, as set by EPSMonitorSet()

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

     86:    Notes:
     87:    Several different monitoring routines may be set by calling
     88:    EPSMonitorSet() multiple times; all will be called in the
     89:    order in which they were set.

     91:    Level: intermediate

     93: .seealso: EPSMonitorFirst(), EPSMonitorAll(), EPSMonitorCancel()
     94: @*/
     95: PetscErrorCode EPSMonitorSet(EPS eps,PetscErrorCode (*monitor)(EPS eps,PetscInt its,PetscInt nconv,PetscScalar *eigr,PetscScalar *eigi,PetscReal *errest,PetscInt nest,void *mctx),void *mctx,PetscErrorCode (*monitordestroy)(void**))
     96: {
     97:   PetscFunctionBegin;
     99:   PetscCheck(eps->numbermonitors<MAXEPSMONITORS,PetscObjectComm((PetscObject)eps),PETSC_ERR_ARG_OUTOFRANGE,"Too many EPS monitors set");
    100:   eps->monitor[eps->numbermonitors]           = monitor;
    101:   eps->monitorcontext[eps->numbermonitors]    = (void*)mctx;
    102:   eps->monitordestroy[eps->numbermonitors++]  = monitordestroy;
    103:   PetscFunctionReturn(PETSC_SUCCESS);
    104: }

    106: /*@
    107:    EPSMonitorCancel - Clears all monitors for an EPS object.

    109:    Logically Collective

    111:    Input Parameters:
    112: .  eps - eigensolver context obtained from EPSCreate()

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

    119:    Level: intermediate

    121: .seealso: EPSMonitorSet()
    122: @*/
    123: PetscErrorCode EPSMonitorCancel(EPS eps)
    124: {
    125:   PetscInt       i;

    127:   PetscFunctionBegin;
    129:   for (i=0; i<eps->numbermonitors; i++) {
    130:     if (eps->monitordestroy[i]) PetscCall((*eps->monitordestroy[i])(&eps->monitorcontext[i]));
    131:   }
    132:   eps->numbermonitors = 0;
    133:   PetscFunctionReturn(PETSC_SUCCESS);
    134: }

    136: /*@C
    137:    EPSGetMonitorContext - Gets the monitor context, as set by
    138:    EPSMonitorSet() for the FIRST monitor only.

    140:    Not Collective

    142:    Input Parameter:
    143: .  eps - eigensolver context obtained from EPSCreate()

    145:    Output Parameter:
    146: .  ctx - monitor context

    148:    Level: intermediate

    150: .seealso: EPSMonitorSet()
    151: @*/
    152: PetscErrorCode EPSGetMonitorContext(EPS eps,void *ctx)
    153: {
    154:   PetscFunctionBegin;
    156:   *(void**)ctx = eps->monitorcontext[0];
    157:   PetscFunctionReturn(PETSC_SUCCESS);
    158: }

    160: /*@C
    161:    EPSMonitorFirst - Print the first unconverged approximate value and
    162:    error estimate at each iteration of the eigensolver.

    164:    Collective

    166:    Input Parameters:
    167: +  eps    - eigensolver context
    168: .  its    - iteration number
    169: .  nconv  - number of converged eigenpairs so far
    170: .  eigr   - real part of the eigenvalues
    171: .  eigi   - imaginary part of the eigenvalues
    172: .  errest - error estimates
    173: .  nest   - number of error estimates to display
    174: -  vf     - viewer and format for monitoring

    176:    Options Database Key:
    177: .  -eps_monitor - activates EPSMonitorFirst()

    179:    Level: intermediate

    181: .seealso: EPSMonitorSet(), EPSMonitorAll(), EPSMonitorConverged()
    182: @*/
    183: PetscErrorCode EPSMonitorFirst(EPS eps,PetscInt its,PetscInt nconv,PetscScalar *eigr,PetscScalar *eigi,PetscReal *errest,PetscInt nest,PetscViewerAndFormat *vf)
    184: {
    185:   PetscScalar    er,ei;
    186:   PetscViewer    viewer = vf->viewer;

    188:   PetscFunctionBegin;
    191:   if (its==1 && ((PetscObject)eps)->prefix) PetscCall(PetscViewerASCIIPrintf(viewer,"  Eigenvalue approximations and residual norms for %s solve.\n",((PetscObject)eps)->prefix));
    192:   if (nconv<nest) {
    193:     PetscCall(PetscViewerPushFormat(viewer,vf->format));
    194:     PetscCall(PetscViewerASCIIAddTab(viewer,((PetscObject)eps)->tablevel));
    195:     PetscCall(PetscViewerASCIIPrintf(viewer,"%3" PetscInt_FMT " EPS nconv=%" PetscInt_FMT " first unconverged value (error)",its,nconv));
    196:     PetscCall(PetscViewerASCIIUseTabs(viewer,PETSC_FALSE));
    197:     er = eigr[nconv]; ei = eigi[nconv];
    198:     PetscCall(STBackTransform(eps->st,1,&er,&ei));
    199: #if defined(PETSC_USE_COMPLEX)
    200:     PetscCall(PetscViewerASCIIPrintf(viewer," %g%+gi",(double)PetscRealPart(er),(double)PetscImaginaryPart(er)));
    201: #else
    202:     PetscCall(PetscViewerASCIIPrintf(viewer," %g",(double)er));
    203:     if (ei!=0.0) PetscCall(PetscViewerASCIIPrintf(viewer,"%+gi",(double)ei));
    204: #endif
    205:     PetscCall(PetscViewerASCIIPrintf(viewer," (%10.8e)\n",(double)errest[nconv]));
    206:     PetscCall(PetscViewerASCIIUseTabs(viewer,PETSC_TRUE));
    207:     PetscCall(PetscViewerASCIISubtractTab(viewer,((PetscObject)eps)->tablevel));
    208:     PetscCall(PetscViewerPopFormat(viewer));
    209:   }
    210:   PetscFunctionReturn(PETSC_SUCCESS);
    211: }

    213: /*@C
    214:    EPSMonitorAll - Print the current approximate values and
    215:    error estimates at each iteration of the eigensolver.

    217:    Collective

    219:    Input Parameters:
    220: +  eps    - eigensolver context
    221: .  its    - iteration number
    222: .  nconv  - number of converged eigenpairs so far
    223: .  eigr   - real part of the eigenvalues
    224: .  eigi   - imaginary part of the eigenvalues
    225: .  errest - error estimates
    226: .  nest   - number of error estimates to display
    227: -  vf     - viewer and format for monitoring

    229:    Options Database Key:
    230: .  -eps_monitor_all - activates EPSMonitorAll()

    232:    Level: intermediate

    234: .seealso: EPSMonitorSet(), EPSMonitorFirst(), EPSMonitorConverged()
    235: @*/
    236: PetscErrorCode EPSMonitorAll(EPS eps,PetscInt its,PetscInt nconv,PetscScalar *eigr,PetscScalar *eigi,PetscReal *errest,PetscInt nest,PetscViewerAndFormat *vf)
    237: {
    238:   PetscInt       i;
    239:   PetscScalar    er,ei;
    240:   PetscViewer    viewer = vf->viewer;

    242:   PetscFunctionBegin;
    245:   PetscCall(PetscViewerPushFormat(viewer,vf->format));
    246:   PetscCall(PetscViewerASCIIAddTab(viewer,((PetscObject)eps)->tablevel));
    247:   if (its==1 && ((PetscObject)eps)->prefix) PetscCall(PetscViewerASCIIPrintf(viewer,"  Eigenvalue approximations and residual norms for %s solve.\n",((PetscObject)eps)->prefix));
    248:   PetscCall(PetscViewerASCIIPrintf(viewer,"%3" PetscInt_FMT " EPS nconv=%" PetscInt_FMT " Values (Errors)",its,nconv));
    249:   PetscCall(PetscViewerASCIIUseTabs(viewer,PETSC_FALSE));
    250:   for (i=0;i<nest;i++) {
    251:     er = eigr[i]; ei = eigi[i];
    252:     PetscCall(STBackTransform(eps->st,1,&er,&ei));
    253: #if defined(PETSC_USE_COMPLEX)
    254:     PetscCall(PetscViewerASCIIPrintf(viewer," %g%+gi",(double)PetscRealPart(er),(double)PetscImaginaryPart(er)));
    255: #else
    256:     PetscCall(PetscViewerASCIIPrintf(viewer," %g",(double)er));
    257:     if (ei!=0.0) PetscCall(PetscViewerASCIIPrintf(viewer,"%+gi",(double)ei));
    258: #endif
    259:     PetscCall(PetscViewerASCIIPrintf(viewer," (%10.8e)",(double)errest[i]));
    260:   }
    261:   PetscCall(PetscViewerASCIIPrintf(viewer,"\n"));
    262:   PetscCall(PetscViewerASCIIUseTabs(viewer,PETSC_TRUE));
    263:   PetscCall(PetscViewerASCIISubtractTab(viewer,((PetscObject)eps)->tablevel));
    264:   PetscCall(PetscViewerPopFormat(viewer));
    265:   PetscFunctionReturn(PETSC_SUCCESS);
    266: }

    268: /*@C
    269:    EPSMonitorConverged - Print the approximate values and
    270:    error estimates as they converge.

    272:    Collective

    274:    Input Parameters:
    275: +  eps    - eigensolver context
    276: .  its    - iteration number
    277: .  nconv  - number of converged eigenpairs so far
    278: .  eigr   - real part of the eigenvalues
    279: .  eigi   - imaginary part of the eigenvalues
    280: .  errest - error estimates
    281: .  nest   - number of error estimates to display
    282: -  vf     - viewer and format for monitoring

    284:    Options Database Key:
    285: .  -eps_monitor_conv - activates EPSMonitorConverged()

    287:    Level: intermediate

    289: .seealso: EPSMonitorSet(), EPSMonitorFirst(), EPSMonitorAll()
    290: @*/
    291: PetscErrorCode EPSMonitorConverged(EPS eps,PetscInt its,PetscInt nconv,PetscScalar *eigr,PetscScalar *eigi,PetscReal *errest,PetscInt nest,PetscViewerAndFormat *vf)
    292: {
    293:   PetscInt       i;
    294:   PetscScalar    er,ei;
    295:   PetscViewer    viewer = vf->viewer;
    296:   SlepcConvMon   ctx;

    298:   PetscFunctionBegin;
    301:   ctx = (SlepcConvMon)vf->data;
    302:   if (its==1 && ((PetscObject)eps)->prefix) PetscCall(PetscViewerASCIIPrintf(viewer,"  Convergence history for %s solve.\n",((PetscObject)eps)->prefix));
    303:   if (its==1) ctx->oldnconv = 0;
    304:   if (ctx->oldnconv!=nconv) {
    305:     PetscCall(PetscViewerPushFormat(viewer,vf->format));
    306:     PetscCall(PetscViewerASCIIAddTab(viewer,((PetscObject)eps)->tablevel));
    307:     for (i=ctx->oldnconv;i<nconv;i++) {
    308:       PetscCall(PetscViewerASCIIPrintf(viewer,"%3" PetscInt_FMT " EPS converged value (error) #%" PetscInt_FMT,its,i));
    309:       PetscCall(PetscViewerASCIIUseTabs(viewer,PETSC_FALSE));
    310:       er = eigr[i]; ei = eigi[i];
    311:       PetscCall(STBackTransform(eps->st,1,&er,&ei));
    312: #if defined(PETSC_USE_COMPLEX)
    313:       PetscCall(PetscViewerASCIIPrintf(viewer," %g%+gi",(double)PetscRealPart(er),(double)PetscImaginaryPart(er)));
    314: #else
    315:       PetscCall(PetscViewerASCIIPrintf(viewer," %g",(double)er));
    316:       if (ei!=0.0) PetscCall(PetscViewerASCIIPrintf(viewer,"%+gi",(double)ei));
    317: #endif
    318:       PetscCall(PetscViewerASCIIPrintf(viewer," (%10.8e)\n",(double)errest[i]));
    319:       PetscCall(PetscViewerASCIIUseTabs(viewer,PETSC_TRUE));
    320:     }
    321:     PetscCall(PetscViewerASCIISubtractTab(viewer,((PetscObject)eps)->tablevel));
    322:     PetscCall(PetscViewerPopFormat(viewer));
    323:     ctx->oldnconv = nconv;
    324:   }
    325:   PetscFunctionReturn(PETSC_SUCCESS);
    326: }

    328: PetscErrorCode EPSMonitorConvergedCreate(PetscViewer viewer,PetscViewerFormat format,void *ctx,PetscViewerAndFormat **vf)
    329: {
    330:   SlepcConvMon   mctx;

    332:   PetscFunctionBegin;
    333:   PetscCall(PetscViewerAndFormatCreate(viewer,format,vf));
    334:   PetscCall(PetscNew(&mctx));
    335:   mctx->ctx = ctx;
    336:   (*vf)->data = (void*)mctx;
    337:   PetscFunctionReturn(PETSC_SUCCESS);
    338: }

    340: PetscErrorCode EPSMonitorConvergedDestroy(PetscViewerAndFormat **vf)
    341: {
    342:   PetscFunctionBegin;
    343:   if (!*vf) PetscFunctionReturn(PETSC_SUCCESS);
    344:   PetscCall(PetscFree((*vf)->data));
    345:   PetscCall(PetscOptionsRestoreViewer(&(*vf)->viewer));
    346:   PetscCall(PetscDrawLGDestroy(&(*vf)->lg));
    347:   PetscCall(PetscFree(*vf));
    348:   PetscFunctionReturn(PETSC_SUCCESS);
    349: }

    351: /*@C
    352:    EPSMonitorFirstDrawLG - Plots the error estimate of the first unconverged
    353:    approximation at each iteration of the eigensolver.

    355:    Collective

    357:    Input Parameters:
    358: +  eps    - eigensolver context
    359: .  its    - iteration number
    360: .  nconv  - number of converged eigenpairs so far
    361: .  eigr   - real part of the eigenvalues
    362: .  eigi   - imaginary part of the eigenvalues
    363: .  errest - error estimates
    364: .  nest   - number of error estimates to display
    365: -  vf     - viewer and format for monitoring

    367:    Options Database Key:
    368: .  -eps_monitor draw::draw_lg - activates EPSMonitorFirstDrawLG()

    370:    Level: intermediate

    372: .seealso: EPSMonitorSet()
    373: @*/
    374: PetscErrorCode EPSMonitorFirstDrawLG(EPS eps,PetscInt its,PetscInt nconv,PetscScalar *eigr,PetscScalar *eigi,PetscReal *errest,PetscInt nest,PetscViewerAndFormat *vf)
    375: {
    376:   PetscViewer    viewer = vf->viewer;
    377:   PetscDrawLG    lg = vf->lg;
    378:   PetscReal      x,y;

    380:   PetscFunctionBegin;
    384:   PetscCall(PetscViewerPushFormat(viewer,vf->format));
    385:   if (its==1) {
    386:     PetscCall(PetscDrawLGReset(lg));
    387:     PetscCall(PetscDrawLGSetDimension(lg,1));
    388:     PetscCall(PetscDrawLGSetLimits(lg,1,1,PetscLog10Real(eps->tol)-2,0.0));
    389:   }
    390:   if (nconv<nest) {
    391:     x = (PetscReal)its;
    392:     if (errest[nconv] > 0.0) y = PetscLog10Real(errest[nconv]);
    393:     else y = 0.0;
    394:     PetscCall(PetscDrawLGAddPoint(lg,&x,&y));
    395:     if (its <= 20 || !(its % 5) || eps->reason) {
    396:       PetscCall(PetscDrawLGDraw(lg));
    397:       PetscCall(PetscDrawLGSave(lg));
    398:     }
    399:   }
    400:   PetscCall(PetscViewerPopFormat(viewer));
    401:   PetscFunctionReturn(PETSC_SUCCESS);
    402: }

    404: /*@C
    405:    EPSMonitorFirstDrawLGCreate - Creates the plotter for the first error estimate.

    407:    Collective

    409:    Input Parameters:
    410: +  viewer - the viewer
    411: .  format - the viewer format
    412: -  ctx    - an optional user context

    414:    Output Parameter:
    415: .  vf     - the viewer and format context

    417:    Level: intermediate

    419: .seealso: EPSMonitorSet()
    420: @*/
    421: PetscErrorCode EPSMonitorFirstDrawLGCreate(PetscViewer viewer,PetscViewerFormat format,void *ctx,PetscViewerAndFormat **vf)
    422: {
    423:   PetscFunctionBegin;
    424:   PetscCall(PetscViewerAndFormatCreate(viewer,format,vf));
    425:   (*vf)->data = ctx;
    426:   PetscCall(EPSMonitorLGCreate(PetscObjectComm((PetscObject)viewer),NULL,"First Error Estimate","Log Error Estimate",1,NULL,PETSC_DECIDE,PETSC_DECIDE,400,300,&(*vf)->lg));
    427:   PetscFunctionReturn(PETSC_SUCCESS);
    428: }

    430: /*@C
    431:    EPSMonitorAllDrawLG - Plots the error estimate of all unconverged
    432:    approximations at each iteration of the eigensolver.

    434:    Collective

    436:    Input Parameters:
    437: +  eps    - eigensolver context
    438: .  its    - iteration number
    439: .  nconv  - number of converged eigenpairs so far
    440: .  eigr   - real part of the eigenvalues
    441: .  eigi   - imaginary part of the eigenvalues
    442: .  errest - error estimates
    443: .  nest   - number of error estimates to display
    444: -  vf     - viewer and format for monitoring

    446:    Options Database Key:
    447: .  -eps_monitor_all draw::draw_lg - activates EPSMonitorAllDrawLG()

    449:    Level: intermediate

    451: .seealso: EPSMonitorSet()
    452: @*/
    453: PetscErrorCode EPSMonitorAllDrawLG(EPS eps,PetscInt its,PetscInt nconv,PetscScalar *eigr,PetscScalar *eigi,PetscReal *errest,PetscInt nest,PetscViewerAndFormat *vf)
    454: {
    455:   PetscViewer    viewer = vf->viewer;
    456:   PetscDrawLG    lg = vf->lg;
    457:   PetscInt       i,n = PetscMin(eps->nev,255);
    458:   PetscReal      *x,*y;

    460:   PetscFunctionBegin;
    464:   PetscCall(PetscViewerPushFormat(viewer,vf->format));
    465:   if (its==1) {
    466:     PetscCall(PetscDrawLGReset(lg));
    467:     PetscCall(PetscDrawLGSetDimension(lg,n));
    468:     PetscCall(PetscDrawLGSetLimits(lg,1,1,PetscLog10Real(eps->tol)-2,0.0));
    469:   }
    470:   PetscCall(PetscMalloc2(n,&x,n,&y));
    471:   for (i=0;i<n;i++) {
    472:     x[i] = (PetscReal)its;
    473:     if (i < nest && errest[i] > 0.0) y[i] = PetscLog10Real(errest[i]);
    474:     else y[i] = 0.0;
    475:   }
    476:   PetscCall(PetscDrawLGAddPoint(lg,x,y));
    477:   if (its <= 20 || !(its % 5) || eps->reason) {
    478:     PetscCall(PetscDrawLGDraw(lg));
    479:     PetscCall(PetscDrawLGSave(lg));
    480:   }
    481:   PetscCall(PetscFree2(x,y));
    482:   PetscCall(PetscViewerPopFormat(viewer));
    483:   PetscFunctionReturn(PETSC_SUCCESS);
    484: }

    486: /*@C
    487:    EPSMonitorAllDrawLGCreate - Creates the plotter for all the error estimates.

    489:    Collective

    491:    Input Parameters:
    492: +  viewer - the viewer
    493: .  format - the viewer format
    494: -  ctx    - an optional user context

    496:    Output Parameter:
    497: .  vf     - the viewer and format context

    499:    Level: intermediate

    501: .seealso: EPSMonitorSet()
    502: @*/
    503: PetscErrorCode EPSMonitorAllDrawLGCreate(PetscViewer viewer,PetscViewerFormat format,void *ctx,PetscViewerAndFormat **vf)
    504: {
    505:   PetscFunctionBegin;
    506:   PetscCall(PetscViewerAndFormatCreate(viewer,format,vf));
    507:   (*vf)->data = ctx;
    508:   PetscCall(EPSMonitorLGCreate(PetscObjectComm((PetscObject)viewer),NULL,"All Error Estimates","Log Error Estimate",1,NULL,PETSC_DECIDE,PETSC_DECIDE,400,300,&(*vf)->lg));
    509:   PetscFunctionReturn(PETSC_SUCCESS);
    510: }

    512: /*@C
    513:    EPSMonitorConvergedDrawLG - Plots the number of converged eigenvalues
    514:    at each iteration of the eigensolver.

    516:    Collective

    518:    Input Parameters:
    519: +  eps    - eigensolver context
    520: .  its    - iteration number
    521: .  nconv  - number of converged eigenpairs so far
    522: .  eigr   - real part of the eigenvalues
    523: .  eigi   - imaginary part of the eigenvalues
    524: .  errest - error estimates
    525: .  nest   - number of error estimates to display
    526: -  vf     - viewer and format for monitoring

    528:    Options Database Key:
    529: .  -eps_monitor_conv draw::draw_lg - activates EPSMonitorConvergedDrawLG()

    531:    Level: intermediate

    533: .seealso: EPSMonitorSet()
    534: @*/
    535: PetscErrorCode EPSMonitorConvergedDrawLG(EPS eps,PetscInt its,PetscInt nconv,PetscScalar *eigr,PetscScalar *eigi,PetscReal *errest,PetscInt nest,PetscViewerAndFormat *vf)
    536: {
    537:   PetscViewer      viewer = vf->viewer;
    538:   PetscDrawLG      lg = vf->lg;
    539:   PetscReal        x,y;

    541:   PetscFunctionBegin;
    545:   PetscCall(PetscViewerPushFormat(viewer,vf->format));
    546:   if (its==1) {
    547:     PetscCall(PetscDrawLGReset(lg));
    548:     PetscCall(PetscDrawLGSetDimension(lg,1));
    549:     PetscCall(PetscDrawLGSetLimits(lg,1,1,0,eps->nev));
    550:   }
    551:   x = (PetscReal)its;
    552:   y = (PetscReal)eps->nconv;
    553:   PetscCall(PetscDrawLGAddPoint(lg,&x,&y));
    554:   if (its <= 20 || !(its % 5) || eps->reason) {
    555:     PetscCall(PetscDrawLGDraw(lg));
    556:     PetscCall(PetscDrawLGSave(lg));
    557:   }
    558:   PetscCall(PetscViewerPopFormat(viewer));
    559:   PetscFunctionReturn(PETSC_SUCCESS);
    560: }

    562: /*@C
    563:    EPSMonitorConvergedDrawLGCreate - Creates the plotter for the convergence history.

    565:    Collective

    567:    Input Parameters:
    568: +  viewer - the viewer
    569: .  format - the viewer format
    570: -  ctx    - an optional user context

    572:    Output Parameter:
    573: .  vf     - the viewer and format context

    575:    Level: intermediate

    577: .seealso: EPSMonitorSet()
    578: @*/
    579: PetscErrorCode EPSMonitorConvergedDrawLGCreate(PetscViewer viewer,PetscViewerFormat format,void *ctx,PetscViewerAndFormat **vf)
    580: {
    581:   SlepcConvMon   mctx;

    583:   PetscFunctionBegin;
    584:   PetscCall(PetscViewerAndFormatCreate(viewer,format,vf));
    585:   PetscCall(PetscNew(&mctx));
    586:   mctx->ctx = ctx;
    587:   (*vf)->data = (void*)mctx;
    588:   PetscCall(EPSMonitorLGCreate(PetscObjectComm((PetscObject)viewer),NULL,"Convergence History","Number Converged",1,NULL,PETSC_DECIDE,PETSC_DECIDE,400,300,&(*vf)->lg));
    589:   PetscFunctionReturn(PETSC_SUCCESS);
    590: }