Date: 2026-03-31T13:23:24+00:00

Actual source code: nepmon.c

      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: /*
     18:    Runs the user provided monitor routines, if any.
     19: */
     20: PetscErrorCode NEPMonitor(NEP nep,PetscInt it,PetscInt nconv,PetscScalar *eigr,PetscScalar *eigi,PetscReal *errest,PetscInt nest)
     21: {
     22:   PetscInt       i,n = nep->numbermonitors;

     24:   PetscFunctionBegin;
     25:   for (i=0;i<n;i++) PetscCall((*nep->monitor[i])(nep,it,nconv,eigr,eigi,errest,nest,nep->monitorcontext[i]));
     26:   PetscFunctionReturn(PETSC_SUCCESS);
     27: }

     29: /*@C
     30:    NEPMonitorSet - Sets an ADDITIONAL function to be called at every
     31:    iteration to monitor the error estimates for each requested eigenpair.

     33:    Logically Collective

     35:    Input Parameters:
     36: +  nep            - the nonlinear eigensolver context
     37: .  monitor        - pointer to function (if this is `NULL`, it turns off monitoring),
     38:                     see `NEPMonitorFn`
     39: .  ctx            - [optional] context for private data for the monitor routine
     40:                     (use `NULL` if no context is desired)
     41: -  monitordestroy - [optional] routine that frees monitor context (may be `NULL`),
     42:                     see `PetscCtxDestroyFn` for the calling sequence

     44:    Options Database Keys:
     45: +  -nep_monitor                    - print only the first error estimate
     46: .  -nep_monitor_all                - print error estimates at each iteration
     47: .  -nep_monitor_conv               - print the eigenvalue approximations only when
     48:                                      convergence has been reached
     49: .  -nep_monitor draw::draw_lg      - sets line graph monitor for the first unconverged
     50:                                      approximate eigenvalue
     51: .  -nep_monitor_all draw::draw_lg  - sets line graph monitor for all unconverged
     52:                                      approximate eigenvalues
     53: .  -nep_monitor_conv draw::draw_lg - sets line graph monitor for convergence history
     54: -  -nep_monitor_cancel             - cancels all monitors that have been hardwired into
     55:                                      a code by calls to `NEPMonitorSet()`, but does not cancel
     56:                                      those set via the options database.

     58:    Notes:
     59:    The options database option `-nep_monitor` and related options are the easiest way
     60:    to turn on `NEP` iteration monitoring.

     62:    `NEPMonitorRegister()` provides a way to associate an options database key with `NEP`
     63:    monitor function.

     65:    Several different monitoring routines may be set by calling `NEPMonitorSet()` multiple
     66:    times; all will be called in the order in which they were set.

     68:    Fortran Note:
     69:    Only a single monitor function can be set for each `NEP` object.

     71:    Level: intermediate

     73: .seealso: [](ch:nep), `NEPMonitorFirst()`, `NEPMonitorAll()`, `NEPMonitorConverged()`, `NEPMonitorFirstDrawLG()`, `NEPMonitorAllDrawLG()`, `NEPMonitorConvergedDrawLG()`, `NEPMonitorCancel()`
     74: @*/
     75: PetscErrorCode NEPMonitorSet(NEP nep,NEPMonitorFn *monitor,PetscCtx ctx,PetscCtxDestroyFn *monitordestroy)
     76: {
     77:   PetscInt  i;
     78:   PetscBool identical;

     80:   PetscFunctionBegin;
     82:   for (i=0;i<nep->numbermonitors;i++) {
     83:     PetscCall(PetscMonitorCompare((PetscErrorCode(*)(void))(PetscVoidFn*)monitor,ctx,monitordestroy,(PetscErrorCode (*)(void))(PetscVoidFn*)nep->monitor[i],nep->monitorcontext[i],nep->monitordestroy[i],&identical));
     84:     if (identical) PetscFunctionReturn(PETSC_SUCCESS);
     85:   }
     86:   PetscCheck(nep->numbermonitors<MAXNEPMONITORS,PetscObjectComm((PetscObject)nep),PETSC_ERR_ARG_OUTOFRANGE,"Too many NEP monitors set");
     87:   nep->monitor[nep->numbermonitors]           = monitor;
     88:   nep->monitorcontext[nep->numbermonitors]    = ctx;
     89:   nep->monitordestroy[nep->numbermonitors++]  = monitordestroy;
     90:   PetscFunctionReturn(PETSC_SUCCESS);
     91: }

     93: /*@
     94:    NEPMonitorCancel - Clears all monitors for a `NEP` object.

     96:    Logically Collective

     98:    Input Parameter:
     99: .  nep - the nonlinear eigensolver context

    101:    Options Database Key:
    102: .  -nep_monitor_cancel - cancels all monitors that have been hardwired into a code by calls to
    103:                          `NEPMonitorSet()`, but does not cancel those set via the options database.

    105:    Level: intermediate

    107: .seealso: [](ch:nep), `NEPMonitorSet()`
    108: @*/
    109: PetscErrorCode NEPMonitorCancel(NEP nep)
    110: {
    111:   PetscInt       i;

    113:   PetscFunctionBegin;
    115:   for (i=0; i<nep->numbermonitors; i++) {
    116:     if (nep->monitordestroy[i]) PetscCall((*nep->monitordestroy[i])(&nep->monitorcontext[i]));
    117:   }
    118:   nep->numbermonitors = 0;
    119:   PetscFunctionReturn(PETSC_SUCCESS);
    120: }

    122: /*@C
    123:    NEPGetMonitorContext - Gets the monitor context, as set by
    124:    `NEPMonitorSet()` for the FIRST monitor only.

    126:    Not Collective

    128:    Input Parameter:
    129: .  nep - the nonlinear eigensolver context

    131:    Output Parameter:
    132: .  ctx - monitor context

    134:    Level: intermediate

    136: .seealso: [](ch:nep), `NEPMonitorSet()`
    137: @*/
    138: PetscErrorCode NEPGetMonitorContext(NEP nep,PetscCtxRt ctx)
    139: {
    140:   PetscFunctionBegin;
    142:   *(void**)ctx = nep->monitorcontext[0];
    143:   PetscFunctionReturn(PETSC_SUCCESS);
    144: }

    146: /*@C
    147:    NEPMonitorFirst - Print the first unconverged approximate value and
    148:    error estimate at each iteration of the nonlinear eigensolver.

    150:    Collective

    152:    Input Parameters:
    153: +  nep    - the nonlinear eigensolver context
    154: .  its    - iteration number
    155: .  nconv  - number of converged eigenpairs so far
    156: .  eigr   - real part of the eigenvalues
    157: .  eigi   - imaginary part of the eigenvalues
    158: .  errest - error estimates
    159: .  nest   - number of error estimates to display
    160: -  vf     - viewer and format for monitoring

    162:    Options Database Key:
    163: .  -nep_monitor - activates `NEPMonitorFirst()`

    165:    Note:
    166:    This is not called directly by users, rather one calls `NEPMonitorSet()`, with this
    167:    function as an argument, to cause the monitor to be used during the `NEP` solve.

    169:    Level: intermediate

    171: .seealso: [](ch:nep), `NEPMonitorSet()`, `NEPMonitorAll()`, `NEPMonitorConverged()`
    172: @*/
    173: PetscErrorCode NEPMonitorFirst(NEP nep,PetscInt its,PetscInt nconv,PetscScalar eigr[],PetscScalar eigi[],PetscReal errest[],PetscInt nest,PetscViewerAndFormat *vf)
    174: {
    175:   PetscViewer    viewer = vf->viewer;

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

    200: /*@C
    201:    NEPMonitorAll - Print the current approximate values and
    202:    error estimates at each iteration of the nonlinear eigensolver.

    204:    Collective

    206:    Input Parameters:
    207: +  nep    - the nonlinear eigensolver context
    208: .  its    - iteration number
    209: .  nconv  - number of converged eigenpairs so far
    210: .  eigr   - real part of the eigenvalues
    211: .  eigi   - imaginary part of the eigenvalues
    212: .  errest - error estimates
    213: .  nest   - number of error estimates to display
    214: -  vf     - viewer and format for monitoring

    216:    Options Database Key:
    217: .  -nep_monitor_all - activates `NEPMonitorAll()`

    219:    Note:
    220:    This is not called directly by users, rather one calls `NEPMonitorSet()`, with this
    221:    function as an argument, to cause the monitor to be used during the `NEP` solve.

    223:    Level: intermediate

    225: .seealso: [](ch:nep), `NEPMonitorSet()`, `NEPMonitorFirst()`, `NEPMonitorConverged()`
    226: @*/
    227: PetscErrorCode NEPMonitorAll(NEP nep,PetscInt its,PetscInt nconv,PetscScalar eigr[],PetscScalar eigi[],PetscReal errest[],PetscInt nest,PetscViewerAndFormat *vf)
    228: {
    229:   PetscInt       i;
    230:   PetscViewer    viewer = vf->viewer;

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

    256: /*@C
    257:    NEPMonitorConverged - Print the approximate values and
    258:    error estimates as they converge.

    260:    Collective

    262:    Input Parameters:
    263: +  nep    - the nonlinear eigensolver context
    264: .  its    - iteration number
    265: .  nconv  - number of converged eigenpairs so far
    266: .  eigr   - real part of the eigenvalues
    267: .  eigi   - imaginary part of the eigenvalues
    268: .  errest - error estimates
    269: .  nest   - number of error estimates to display
    270: -  vf     - viewer and format for monitoring

    272:    Options Database Key:
    273: .  -nep_monitor_conv - activates `NEPMonitorConverged()`

    275:    Notes:
    276:    This is not called directly by users, rather one calls `NEPMonitorSet()`, with this
    277:    function as an argument, to cause the monitor to be used during the `NEP` solve.

    279:    Call `NEPMonitorConvergedCreate()` to create the context used with this monitor.

    281:    Level: intermediate

    283: .seealso: [](ch:nep), `NEPMonitorSet()`, `NEPMonitorConvergedCreate()`, `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,*oldnconv;
    288:   PetscViewer    viewer = vf->viewer;

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

    318: /*@C
    319:    NEPMonitorConvergedCreate - Creates the context for the convergence history monitor.

    321:    Collective

    323:    Input Parameters:
    324: +  viewer - the viewer
    325: .  format - the viewer format
    326: -  ctx    - an optional user context

    328:    Output Parameter:
    329: .  vf     - the viewer and format context

    331:    Level: intermediate

    333: .seealso: [](ch:nep), `NEPMonitorSet()`
    334: @*/
    335: PetscErrorCode NEPMonitorConvergedCreate(PetscViewer viewer,PetscViewerFormat format,PetscCtx ctx,PetscViewerAndFormat **vf)
    336: {
    337:   PetscInt *oldnconv;

    339:   PetscFunctionBegin;
    340:   PetscCall(PetscViewerAndFormatCreate(viewer,format,vf));
    341:   PetscCall(PetscNew(&oldnconv));
    342:   (*vf)->data = (void*)oldnconv;
    343:   (*vf)->data_destroy = PetscCtxDestroyDefault;
    344:   PetscFunctionReturn(PETSC_SUCCESS);
    345: }

    347: /*@C
    348:    NEPMonitorFirstDrawLG - Plots the error estimate of the first unconverged
    349:    approximation at each iteration of the nonlinear eigensolver.

    351:    Collective

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

    363:    Options Database Key:
    364: .  -nep_monitor draw::draw_lg - activates `NEPMonitorFirstDrawLG()`

    366:    Notes:
    367:    This is not called directly by users, rather one calls `NEPMonitorSet()`, with this
    368:    function as an argument, to cause the monitor to be used during the `NEP` solve.

    370:    Call `NEPMonitorFirstDrawLGCreate()` to create the context used with this monitor.

    372:    Level: intermediate

    374: .seealso: [](ch:nep), `NEPMonitorSet()`, `NEPMonitorFirstDrawLGCreate()`
    375: @*/
    376: PetscErrorCode NEPMonitorFirstDrawLG(NEP nep,PetscInt its,PetscInt nconv,PetscScalar eigr[],PetscScalar eigi[],PetscReal errest[],PetscInt nest,PetscViewerAndFormat *vf)
    377: {
    378:   PetscViewer    viewer = vf->viewer;
    379:   PetscDrawLG    lg;
    380:   PetscReal      x,y;

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

    406: /*@C
    407:    NEPMonitorFirstDrawLGCreate - Creates the plotter for the first error estimate.

    409:    Collective

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

    416:    Output Parameter:
    417: .  vf     - the viewer and format context

    419:    Level: intermediate

    421: .seealso: [](ch:nep), `NEPMonitorSet()`
    422: @*/
    423: PetscErrorCode NEPMonitorFirstDrawLGCreate(PetscViewer viewer,PetscViewerFormat format,void *ctx,PetscViewerAndFormat **vf)
    424: {
    425:   PetscFunctionBegin;
    426:   PetscCall(PetscViewerAndFormatCreate(viewer,format,vf));
    427:   (*vf)->data = ctx;
    428:   PetscCall(PetscViewerMonitorLGSetUp(viewer,NULL,"First Error Estimate","Log Error Estimate",1,NULL,PETSC_DECIDE,PETSC_DECIDE,400,300));
    429:   PetscFunctionReturn(PETSC_SUCCESS);
    430: }

    432: /*@C
    433:    NEPMonitorAllDrawLG - Plots the error estimate of all unconverged
    434:    approximations at each iteration of the nonlinear eigensolver.

    436:    Collective

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

    448:    Options Database Key:
    449: .  -nep_monitor_all draw::draw_lg - activates `NEPMonitorAllDrawLG()`

    451:    Notes:
    452:    This is not called directly by users, rather one calls `NEPMonitorSet()`, with this
    453:    function as an argument, to cause the monitor to be used during the `NEP` solve.

    455:    Call `NEPMonitorAllDrawLGCreate()` to create the context used with this monitor.

    457:    Level: intermediate

    459: .seealso: [](ch:nep), `NEPMonitorSet()`, `NEPMonitorAllDrawLGCreate()`
    460: @*/
    461: PetscErrorCode NEPMonitorAllDrawLG(NEP nep,PetscInt its,PetscInt nconv,PetscScalar eigr[],PetscScalar eigi[],PetscReal errest[],PetscInt nest,PetscViewerAndFormat *vf)
    462: {
    463:   PetscViewer    viewer = vf->viewer;
    464:   PetscDrawLG    lg;
    465:   PetscInt       i,n = PetscMin(nep->nev,255);
    466:   PetscReal      *x,*y;

    468:   PetscFunctionBegin;
    471:   PetscCall(PetscViewerPushFormat(viewer,vf->format));
    472:   PetscCall(PetscViewerDrawGetDrawLG(viewer,0,&lg));
    473:   if (its==1) {
    474:     PetscCall(PetscDrawLGReset(lg));
    475:     PetscCall(PetscDrawLGSetDimension(lg,n));
    476:     PetscCall(PetscDrawLGSetLimits(lg,1,1,PetscLog10Real(nep->tol)-2,0.0));
    477:   }
    478:   PetscCall(PetscMalloc2(n,&x,n,&y));
    479:   for (i=0;i<n;i++) {
    480:     x[i] = (PetscReal)its;
    481:     if (i < nest && errest[i] > 0.0) y[i] = PetscLog10Real(errest[i]);
    482:     else y[i] = 0.0;
    483:   }
    484:   PetscCall(PetscDrawLGAddPoint(lg,x,y));
    485:   if (its <= 20 || !(its % 5) || nep->reason) {
    486:     PetscCall(PetscDrawLGDraw(lg));
    487:     PetscCall(PetscDrawLGSave(lg));
    488:   }
    489:   PetscCall(PetscFree2(x,y));
    490:   PetscCall(PetscViewerPopFormat(viewer));
    491:   PetscFunctionReturn(PETSC_SUCCESS);
    492: }

    494: /*@C
    495:    NEPMonitorAllDrawLGCreate - Creates the plotter for all the error estimates.

    497:    Collective

    499:    Input Parameters:
    500: +  viewer - the viewer
    501: .  format - the viewer format
    502: -  ctx    - an optional user context

    504:    Output Parameter:
    505: .  vf     - the viewer and format context

    507:    Level: intermediate

    509: .seealso: [](ch:nep), `NEPMonitorSet()`
    510: @*/
    511: PetscErrorCode NEPMonitorAllDrawLGCreate(PetscViewer viewer,PetscViewerFormat format,void *ctx,PetscViewerAndFormat **vf)
    512: {
    513:   PetscFunctionBegin;
    514:   PetscCall(PetscViewerAndFormatCreate(viewer,format,vf));
    515:   (*vf)->data = ctx;
    516:   PetscCall(PetscViewerMonitorLGSetUp(viewer,NULL,"All Error Estimates","Log Error Estimate",1,NULL,PETSC_DECIDE,PETSC_DECIDE,400,300));
    517:   PetscFunctionReturn(PETSC_SUCCESS);
    518: }

    520: /*@C
    521:    NEPMonitorConvergedDrawLG - Plots the number of converged eigenvalues
    522:    at each iteration of the nonlinear eigensolver.

    524:    Collective

    526:    Input Parameters:
    527: +  nep    - the nonlinear eigensolver context
    528: .  its    - iteration number
    529: .  nconv  - number of converged eigenpairs so far
    530: .  eigr   - real part of the eigenvalues
    531: .  eigi   - imaginary part of the eigenvalues
    532: .  errest - error estimates
    533: .  nest   - number of error estimates to display
    534: -  vf     - viewer and format for monitoring

    536:    Options Database Key:
    537: .  -nep_monitor_conv draw::draw_lg - activates `NEPMonitorConvergedDrawLG()`

    539:    Notes:
    540:    This is not called directly by users, rather one calls `NEPMonitorSet()`, with this
    541:    function as an argument, to cause the monitor to be used during the `NEP` solve.

    543:    Call `NEPMonitorConvergedDrawLGCreate()` to create the context used with this monitor.

    545:    Level: intermediate

    547: .seealso: [](ch:nep), `NEPMonitorSet()`, `NEPMonitorConvergedDrawLGCreate()`
    548: @*/
    549: PetscErrorCode NEPMonitorConvergedDrawLG(NEP nep,PetscInt its,PetscInt nconv,PetscScalar eigr[],PetscScalar eigi[],PetscReal errest[],PetscInt nest,PetscViewerAndFormat *vf)
    550: {
    551:   PetscViewer      viewer = vf->viewer;
    552:   PetscDrawLG      lg;
    553:   PetscReal        x,y;

    555:   PetscFunctionBegin;
    558:   PetscCall(PetscViewerPushFormat(viewer,vf->format));
    559:   PetscCall(PetscViewerDrawGetDrawLG(viewer,0,&lg));
    560:   if (its==1) {
    561:     PetscCall(PetscDrawLGReset(lg));
    562:     PetscCall(PetscDrawLGSetDimension(lg,1));
    563:     PetscCall(PetscDrawLGSetLimits(lg,1,1,0,nep->nev));
    564:   }
    565:   x = (PetscReal)its;
    566:   y = (PetscReal)nep->nconv;
    567:   PetscCall(PetscDrawLGAddPoint(lg,&x,&y));
    568:   if (its <= 20 || !(its % 5) || nep->reason) {
    569:     PetscCall(PetscDrawLGDraw(lg));
    570:     PetscCall(PetscDrawLGSave(lg));
    571:   }
    572:   PetscCall(PetscViewerPopFormat(viewer));
    573:   PetscFunctionReturn(PETSC_SUCCESS);
    574: }

    576: /*@C
    577:    NEPMonitorConvergedDrawLGCreate - Creates the plotter for the convergence history.

    579:    Collective

    581:    Input Parameters:
    582: +  viewer - the viewer
    583: .  format - the viewer format
    584: -  ctx    - an optional user context

    586:    Output Parameter:
    587: .  vf     - the viewer and format context

    589:    Level: intermediate

    591: .seealso: [](ch:nep), `NEPMonitorSet()`
    592: @*/
    593: PetscErrorCode NEPMonitorConvergedDrawLGCreate(PetscViewer viewer,PetscViewerFormat format,void *ctx,PetscViewerAndFormat **vf)
    594: {
    595:   PetscInt *oldnconv;

    597:   PetscFunctionBegin;
    598:   PetscCall(PetscViewerAndFormatCreate(viewer,format,vf));
    599:   PetscCall(PetscNew(&oldnconv));
    600:   (*vf)->data = (void*)oldnconv;
    601:   (*vf)->data_destroy = PetscCtxDestroyDefault;
    602:   PetscCall(PetscViewerMonitorLGSetUp(viewer,NULL,"Convergence History","Number Converged",1,NULL,PETSC_DECIDE,PETSC_DECIDE,400,300));
    603:   PetscFunctionReturn(PETSC_SUCCESS);
    604: }