Actual source code: nepmon.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:    NEP routines related to monitors
     12: */

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

     17: PetscErrorCode NEPMonitorLGCreate(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 NEPMonitor(NEP nep,PetscInt it,PetscInt nconv,PetscScalar *eigr,PetscScalar *eigi,PetscReal *errest,PetscInt nest)
     40: {
     41:   PetscInt       i,n = nep->numbermonitors;

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

     48: /*@C
     49:    NEPMonitorSet - 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: +  nep     - eigensolver context obtained from NEPCreate()
     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(NEP nep,PetscInt its,PetscInt nconv,PetscScalar *eigr,PetscScalar *eigi,PetscReal *errest,PetscInt nest,void *mctx)
     63: +  nep    - nonlinear eigensolver context obtained from NEPCreate()
     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 - error estimates for each eigenpair
     69: .  nest   - number of error estimates
     70: -  mctx   - optional monitoring context, as set by NEPMonitorSet()

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

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

     91:    Level: intermediate

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

    106: /*@
    107:    NEPMonitorCancel - Clears all monitors for a NEP object.

    109:    Logically Collective

    111:    Input Parameters:
    112: .  nep - eigensolver context obtained from NEPCreate()

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

    119:    Level: intermediate

    121: .seealso: NEPMonitorSet()
    122: @*/
    123: PetscErrorCode NEPMonitorCancel(NEP nep)
    124: {
    125:   PetscInt       i;

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

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

    140:    Not Collective

    142:    Input Parameter:
    143: .  nep - eigensolver context obtained from NEPCreate()

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

    148:    Level: intermediate

    150: .seealso: NEPMonitorSet(), NEPDefaultMonitor()
    151: @*/
    152: PetscErrorCode NEPGetMonitorContext(NEP nep,void *ctx)
    153: {
    154:   PetscFunctionBegin;
    156:   *(void**)ctx = nep->monitorcontext[0];
    157:   PetscFunctionReturn(PETSC_SUCCESS);
    158: }

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

    164:    Collective

    166:    Input Parameters:
    167: +  nep    - nonlinear 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: .  -nep_monitor - activates NEPMonitorFirst()

    179:    Level: intermediate

    181: .seealso: NEPMonitorSet(), NEPMonitorAll(), NEPMonitorConverged()
    182: @*/
    183: PetscErrorCode NEPMonitorFirst(NEP nep,PetscInt its,PetscInt nconv,PetscScalar *eigr,PetscScalar *eigi,PetscReal *errest,PetscInt nest,PetscViewerAndFormat *vf)
    184: {
    185:   PetscViewer    viewer = vf->viewer;

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

    210: /*@C
    211:    NEPMonitorAll - Print the current approximate values and
    212:    error estimates at each iteration of the nonlinear eigensolver.

    214:    Collective

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

    226:    Options Database Key:
    227: .  -nep_monitor_all - activates NEPMonitorAll()

    229:    Level: intermediate

    231: .seealso: NEPMonitorSet(), NEPMonitorFirst(), NEPMonitorConverged()
    232: @*/
    233: PetscErrorCode NEPMonitorAll(NEP nep,PetscInt its,PetscInt nconv,PetscScalar *eigr,PetscScalar *eigi,PetscReal *errest,PetscInt nest,PetscViewerAndFormat *vf)
    234: {
    235:   PetscInt       i;
    236:   PetscViewer    viewer = vf->viewer;

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

    262: /*@C
    263:    NEPMonitorConverged - Print the approximate values and
    264:    error estimates as they converge.

    266:    Collective

    268:    Input Parameters:
    269: +  nep    - nonlinear eigensolver context
    270: .  its    - iteration number
    271: .  nconv  - number of converged eigenpairs so far
    272: .  eigr   - real part of the eigenvalues
    273: .  eigi   - imaginary part of the eigenvalues
    274: .  errest - error estimates
    275: .  nest   - number of error estimates to display
    276: -  vf     - viewer and format for monitoring

    278:    Options Database Key:
    279: .  -nep_monitor_conv - activates NEPMonitorConverged()

    281:    Level: intermediate

    283: .seealso: NEPMonitorSet(), NEPMonitorFirst(), NEPMonitorAll()
    284: @*/
    285: PetscErrorCode NEPMonitorConverged(NEP nep,PetscInt its,PetscInt nconv,PetscScalar *eigr,PetscScalar *eigi,PetscReal *errest,PetscInt nest,PetscViewerAndFormat *vf)
    286: {
    287:   PetscInt       i;
    288:   PetscViewer    viewer = vf->viewer;
    289:   SlepcConvMon   ctx;

    291:   PetscFunctionBegin;
    294:   ctx = (SlepcConvMon)vf->data;
    295:   if (its==1 && ((PetscObject)nep)->prefix) PetscCall(PetscViewerASCIIPrintf(viewer,"  Convergence history for %s solve.\n",((PetscObject)nep)->prefix));
    296:   if (its==1) ctx->oldnconv = 0;
    297:   if (ctx->oldnconv!=nconv) {
    298:     PetscCall(PetscViewerPushFormat(viewer,vf->format));
    299:     PetscCall(PetscViewerASCIIAddTab(viewer,((PetscObject)nep)->tablevel));
    300:     for (i=ctx->oldnconv;i<nconv;i++) {
    301:       PetscCall(PetscViewerASCIIPrintf(viewer,"%3" PetscInt_FMT " NEP converged value (error) #%" PetscInt_FMT,its,i));
    302:       PetscCall(PetscViewerASCIIUseTabs(viewer,PETSC_FALSE));
    303: #if defined(PETSC_USE_COMPLEX)
    304:       PetscCall(PetscViewerASCIIPrintf(viewer," %g%+gi",(double)PetscRealPart(eigr[i]),(double)PetscImaginaryPart(eigr[i])));
    305: #else
    306:       PetscCall(PetscViewerASCIIPrintf(viewer," %g",(double)eigr[i]));
    307:       if (eigi[i]!=0.0) PetscCall(PetscViewerASCIIPrintf(viewer,"%+gi",(double)eigi[i]));
    308: #endif
    309:       PetscCall(PetscViewerASCIIPrintf(viewer," (%10.8e)\n",(double)errest[i]));
    310:       PetscCall(PetscViewerASCIIUseTabs(viewer,PETSC_TRUE));
    311:     }
    312:     PetscCall(PetscViewerASCIISubtractTab(viewer,((PetscObject)nep)->tablevel));
    313:     PetscCall(PetscViewerPopFormat(viewer));
    314:     ctx->oldnconv = nconv;
    315:   }
    316:   PetscFunctionReturn(PETSC_SUCCESS);
    317: }

    319: PetscErrorCode NEPMonitorConvergedCreate(PetscViewer viewer,PetscViewerFormat format,void *ctx,PetscViewerAndFormat **vf)
    320: {
    321:   SlepcConvMon   mctx;

    323:   PetscFunctionBegin;
    324:   PetscCall(PetscViewerAndFormatCreate(viewer,format,vf));
    325:   PetscCall(PetscNew(&mctx));
    326:   mctx->ctx = ctx;
    327:   (*vf)->data = (void*)mctx;
    328:   PetscFunctionReturn(PETSC_SUCCESS);
    329: }

    331: PetscErrorCode NEPMonitorConvergedDestroy(PetscViewerAndFormat **vf)
    332: {
    333:   PetscFunctionBegin;
    334:   if (!*vf) PetscFunctionReturn(PETSC_SUCCESS);
    335:   PetscCall(PetscFree((*vf)->data));
    336:   PetscCall(PetscOptionsRestoreViewer(&(*vf)->viewer));
    337:   PetscCall(PetscDrawLGDestroy(&(*vf)->lg));
    338:   PetscCall(PetscFree(*vf));
    339:   PetscFunctionReturn(PETSC_SUCCESS);
    340: }

    342: /*@C
    343:    NEPMonitorFirstDrawLG - Plots the error estimate of the first unconverged
    344:    approximation at each iteration of the nonlinear eigensolver.

    346:    Collective

    348:    Input Parameters:
    349: +  nep    - nonlinear eigensolver context
    350: .  its    - iteration number
    351: .  nconv  - number of converged eigenpairs so far
    352: .  eigr   - real part of the eigenvalues
    353: .  eigi   - imaginary part of the eigenvalues
    354: .  errest - error estimates
    355: .  nest   - number of error estimates to display
    356: -  vf     - viewer and format for monitoring

    358:    Options Database Key:
    359: .  -nep_monitor draw::draw_lg - activates NEPMonitorFirstDrawLG()

    361:    Level: intermediate

    363: .seealso: NEPMonitorSet()
    364: @*/
    365: PetscErrorCode NEPMonitorFirstDrawLG(NEP nep,PetscInt its,PetscInt nconv,PetscScalar *eigr,PetscScalar *eigi,PetscReal *errest,PetscInt nest,PetscViewerAndFormat *vf)
    366: {
    367:   PetscViewer    viewer = vf->viewer;
    368:   PetscDrawLG    lg = vf->lg;
    369:   PetscReal      x,y;

    371:   PetscFunctionBegin;
    375:   PetscCall(PetscViewerPushFormat(viewer,vf->format));
    376:   if (its==1) {
    377:     PetscCall(PetscDrawLGReset(lg));
    378:     PetscCall(PetscDrawLGSetDimension(lg,1));
    379:     PetscCall(PetscDrawLGSetLimits(lg,1,1,PetscLog10Real(nep->tol)-2,0.0));
    380:   }
    381:   if (nconv<nest) {
    382:     x = (PetscReal)its;
    383:     if (errest[nconv] > 0.0) y = PetscLog10Real(errest[nconv]);
    384:     else y = 0.0;
    385:     PetscCall(PetscDrawLGAddPoint(lg,&x,&y));
    386:     if (its <= 20 || !(its % 5) || nep->reason) {
    387:       PetscCall(PetscDrawLGDraw(lg));
    388:       PetscCall(PetscDrawLGSave(lg));
    389:     }
    390:   }
    391:   PetscCall(PetscViewerPopFormat(viewer));
    392:   PetscFunctionReturn(PETSC_SUCCESS);
    393: }

    395: /*@C
    396:    NEPMonitorFirstDrawLGCreate - Creates the plotter for the first error estimate.

    398:    Collective

    400:    Input Parameters:
    401: +  viewer - the viewer
    402: .  format - the viewer format
    403: -  ctx    - an optional user context

    405:    Output Parameter:
    406: .  vf     - the viewer and format context

    408:    Level: intermediate

    410: .seealso: NEPMonitorSet()
    411: @*/
    412: PetscErrorCode NEPMonitorFirstDrawLGCreate(PetscViewer viewer,PetscViewerFormat format,void *ctx,PetscViewerAndFormat **vf)
    413: {
    414:   PetscFunctionBegin;
    415:   PetscCall(PetscViewerAndFormatCreate(viewer,format,vf));
    416:   (*vf)->data = ctx;
    417:   PetscCall(NEPMonitorLGCreate(PetscObjectComm((PetscObject)viewer),NULL,"First Error Estimate","Log Error Estimate",1,NULL,PETSC_DECIDE,PETSC_DECIDE,400,300,&(*vf)->lg));
    418:   PetscFunctionReturn(PETSC_SUCCESS);
    419: }

    421: /*@C
    422:    NEPMonitorAllDrawLG - Plots the error estimate of all unconverged
    423:    approximations at each iteration of the nonlinear eigensolver.

    425:    Collective

    427:    Input Parameters:
    428: +  nep    - nonlinear eigensolver context
    429: .  its    - iteration number
    430: .  nconv  - number of converged eigenpairs so far
    431: .  eigr   - real part of the eigenvalues
    432: .  eigi   - imaginary part of the eigenvalues
    433: .  errest - error estimates
    434: .  nest   - number of error estimates to display
    435: -  vf     - viewer and format for monitoring

    437:    Options Database Key:
    438: .  -nep_monitor_all draw::draw_lg - activates NEPMonitorAllDrawLG()

    440:    Level: intermediate

    442: .seealso: NEPMonitorSet()
    443: @*/
    444: PetscErrorCode NEPMonitorAllDrawLG(NEP nep,PetscInt its,PetscInt nconv,PetscScalar *eigr,PetscScalar *eigi,PetscReal *errest,PetscInt nest,PetscViewerAndFormat *vf)
    445: {
    446:   PetscViewer    viewer = vf->viewer;
    447:   PetscDrawLG    lg = vf->lg;
    448:   PetscInt       i,n = PetscMin(nep->nev,255);
    449:   PetscReal      *x,*y;

    451:   PetscFunctionBegin;
    455:   PetscCall(PetscViewerPushFormat(viewer,vf->format));
    456:   if (its==1) {
    457:     PetscCall(PetscDrawLGReset(lg));
    458:     PetscCall(PetscDrawLGSetDimension(lg,n));
    459:     PetscCall(PetscDrawLGSetLimits(lg,1,1,PetscLog10Real(nep->tol)-2,0.0));
    460:   }
    461:   PetscCall(PetscMalloc2(n,&x,n,&y));
    462:   for (i=0;i<n;i++) {
    463:     x[i] = (PetscReal)its;
    464:     if (i < nest && errest[i] > 0.0) y[i] = PetscLog10Real(errest[i]);
    465:     else y[i] = 0.0;
    466:   }
    467:   PetscCall(PetscDrawLGAddPoint(lg,x,y));
    468:   if (its <= 20 || !(its % 5) || nep->reason) {
    469:     PetscCall(PetscDrawLGDraw(lg));
    470:     PetscCall(PetscDrawLGSave(lg));
    471:   }
    472:   PetscCall(PetscFree2(x,y));
    473:   PetscCall(PetscViewerPopFormat(viewer));
    474:   PetscFunctionReturn(PETSC_SUCCESS);
    475: }

    477: /*@C
    478:    NEPMonitorAllDrawLGCreate - Creates the plotter for all the error estimates.

    480:    Collective

    482:    Input Parameters:
    483: +  viewer - the viewer
    484: .  format - the viewer format
    485: -  ctx    - an optional user context

    487:    Output Parameter:
    488: .  vf     - the viewer and format context

    490:    Level: intermediate

    492: .seealso: NEPMonitorSet()
    493: @*/
    494: PetscErrorCode NEPMonitorAllDrawLGCreate(PetscViewer viewer,PetscViewerFormat format,void *ctx,PetscViewerAndFormat **vf)
    495: {
    496:   PetscFunctionBegin;
    497:   PetscCall(PetscViewerAndFormatCreate(viewer,format,vf));
    498:   (*vf)->data = ctx;
    499:   PetscCall(NEPMonitorLGCreate(PetscObjectComm((PetscObject)viewer),NULL,"All Error Estimates","Log Error Estimate",1,NULL,PETSC_DECIDE,PETSC_DECIDE,400,300,&(*vf)->lg));
    500:   PetscFunctionReturn(PETSC_SUCCESS);
    501: }

    503: /*@C
    504:    NEPMonitorConvergedDrawLG - Plots the number of converged eigenvalues
    505:    at each iteration of the nonlinear eigensolver.

    507:    Collective

    509:    Input Parameters:
    510: +  nep    - nonlinear eigensolver context
    511: .  its    - iteration number
    512: .  nconv  - number of converged eigenpairs so far
    513: .  eigr   - real part of the eigenvalues
    514: .  eigi   - imaginary part of the eigenvalues
    515: .  errest - error estimates
    516: .  nest   - number of error estimates to display
    517: -  vf     - viewer and format for monitoring

    519:    Options Database Key:
    520: .  -nep_monitor_conv draw::draw_lg - activates NEPMonitorConvergedDrawLG()

    522:    Level: intermediate

    524: .seealso: NEPMonitorSet()
    525: @*/
    526: PetscErrorCode NEPMonitorConvergedDrawLG(NEP nep,PetscInt its,PetscInt nconv,PetscScalar *eigr,PetscScalar *eigi,PetscReal *errest,PetscInt nest,PetscViewerAndFormat *vf)
    527: {
    528:   PetscViewer      viewer = vf->viewer;
    529:   PetscDrawLG      lg = vf->lg;
    530:   PetscReal        x,y;

    532:   PetscFunctionBegin;
    536:   PetscCall(PetscViewerPushFormat(viewer,vf->format));
    537:   if (its==1) {
    538:     PetscCall(PetscDrawLGReset(lg));
    539:     PetscCall(PetscDrawLGSetDimension(lg,1));
    540:     PetscCall(PetscDrawLGSetLimits(lg,1,1,0,nep->nev));
    541:   }
    542:   x = (PetscReal)its;
    543:   y = (PetscReal)nep->nconv;
    544:   PetscCall(PetscDrawLGAddPoint(lg,&x,&y));
    545:   if (its <= 20 || !(its % 5) || nep->reason) {
    546:     PetscCall(PetscDrawLGDraw(lg));
    547:     PetscCall(PetscDrawLGSave(lg));
    548:   }
    549:   PetscCall(PetscViewerPopFormat(viewer));
    550:   PetscFunctionReturn(PETSC_SUCCESS);
    551: }

    553: /*@C
    554:    NEPMonitorConvergedDrawLGCreate - Creates the plotter for the convergence history.

    556:    Collective

    558:    Input Parameters:
    559: +  viewer - the viewer
    560: .  format - the viewer format
    561: -  ctx    - an optional user context

    563:    Output Parameter:
    564: .  vf     - the viewer and format context

    566:    Level: intermediate

    568: .seealso: NEPMonitorSet()
    569: @*/
    570: PetscErrorCode NEPMonitorConvergedDrawLGCreate(PetscViewer viewer,PetscViewerFormat format,void *ctx,PetscViewerAndFormat **vf)
    571: {
    572:   SlepcConvMon   mctx;

    574:   PetscFunctionBegin;
    575:   PetscCall(PetscViewerAndFormatCreate(viewer,format,vf));
    576:   PetscCall(PetscNew(&mctx));
    577:   mctx->ctx = ctx;
    578:   (*vf)->data = (void*)mctx;
    579:   PetscCall(NEPMonitorLGCreate(PetscObjectComm((PetscObject)viewer),NULL,"Convergence History","Number Converged",1,NULL,PETSC_DECIDE,PETSC_DECIDE,400,300,&(*vf)->lg));
    580:   PetscFunctionReturn(PETSC_SUCCESS);
    581: }