Date: 2026-01-20T11:35:10+00:00

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

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

     17: /*
     18:    Runs the user provided monitor routines, if any.
     19: */
     20: PetscErrorCode PEPMonitor(PEP pep,PetscInt it,PetscInt nconv,PetscScalar *eigr,PetscScalar *eigi,PetscReal *errest,PetscInt nest)
     21: {
     22:   PetscInt       i,n = pep->numbermonitors;

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

     29: /*@C
     30:    PEPMonitorSet - 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: +  pep            - the polynomial eigensolver context
     37: .  monitor        - pointer to function (if this is `NULL`, it turns off monitoring),
     38:                     see `PEPMonitorFn`
     39: .  mctx           - [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: +  -pep_monitor                    - print only the first error estimate
     46: .  -pep_monitor_all                - print error estimates at each iteration
     47: .  -pep_monitor_conv               - print the eigenvalue approximations only when
     48:                                      convergence has been reached
     49: .  -pep_monitor draw::draw_lg      - sets line graph monitor for the first unconverged
     50:                                      approximate eigenvalue
     51: .  -pep_monitor_all draw::draw_lg  - sets line graph monitor for all unconverged
     52:                                      approximate eigenvalues
     53: .  -pep_monitor_conv draw::draw_lg - sets line graph monitor for convergence history
     54: -  -pep_monitor_cancel             - cancels all monitors that have been hardwired into
     55:                                      a code by calls to `PEPMonitorSet()`, but does not cancel
     56:                                      those set via the options database.

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

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

     65:    Several different monitoring routines may be set by calling `PEPMonitorSet()` 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 `PEP` object.

     71:    Level: intermediate

     73: .seealso: [](ch:pep), `PEPMonitorFirst()`, `PEPMonitorAll()`, `PEPMonitorConverged()`, `PEPMonitorFirstDrawLG()`, `PEPMonitorAllDrawLG()`, `PEPMonitorConvergedDrawLG()`, `PEPMonitorCancel()`
     74: @*/
     75: PetscErrorCode PEPMonitorSet(PEP pep,PEPMonitorFn *monitor,void *mctx,PetscCtxDestroyFn *monitordestroy)
     76: {
     77:   PetscInt  i;
     78:   PetscBool identical;

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

     93: /*@
     94:    PEPMonitorCancel - Clears all monitors for a `PEP` object.

     96:    Logically Collective

     98:    Input Parameter:
     99: .  pep - the polynomial eigensolver context

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

    105:    Level: intermediate

    107: .seealso: [](ch:pep), `PEPMonitorSet()`
    108: @*/
    109: PetscErrorCode PEPMonitorCancel(PEP pep)
    110: {
    111:   PetscInt       i;

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

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

    126:    Not Collective

    128:    Input Parameter:
    129: .  pep - the polynomial eigensolver context

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

    134:    Level: intermediate

    136: .seealso: [](ch:pep), `PEPMonitorSet()`
    137: @*/
    138: PetscErrorCode PEPGetMonitorContext(PEP pep,void *ctx)
    139: {
    140:   PetscFunctionBegin;
    142:   *(void**)ctx = pep->monitorcontext[0];
    143:   PetscFunctionReturn(PETSC_SUCCESS);
    144: }

    146: /*
    147:    Helper function to compute eigenvalue that must be viewed in monitor
    148:  */
    149: static PetscErrorCode PEPMonitorGetTrueEig(PEP pep,PetscScalar *er,PetscScalar *ei)
    150: {
    151:   PetscBool      flg,sinv;

    153:   PetscFunctionBegin;
    154:   PetscCall(STBackTransform(pep->st,1,er,ei));
    155:   if (pep->sfactor!=1.0) {
    156:     PetscCall(STGetTransform(pep->st,&flg));
    157:     PetscCall(PetscObjectTypeCompare((PetscObject)pep->st,STSINVERT,&sinv));
    158:     if (flg && sinv) {
    159:       *er /= pep->sfactor; *ei /= pep->sfactor;
    160:     } else {
    161:       *er *= pep->sfactor; *ei *= pep->sfactor;
    162:     }
    163:   }
    164:   PetscFunctionReturn(PETSC_SUCCESS);
    165: }

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

    171:    Collective

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

    183:    Options Database Key:
    184: .  -pep_monitor - activates `PEPMonitorFirst()`

    186:    Note:
    187:    This is not called directly by users, rather one calls `PEPMonitorSet()`, with this
    188:    function as an argument, to cause the monitor to be used during the `PEP` solve.

    190:    Level: intermediate

    192: .seealso: [](ch:pep), `PEPMonitorSet()`, `PEPMonitorAll()`, `PEPMonitorConverged()`
    193: @*/
    194: PetscErrorCode PEPMonitorFirst(PEP pep,PetscInt its,PetscInt nconv,PetscScalar eigr[],PetscScalar eigi[],PetscReal errest[],PetscInt nest,PetscViewerAndFormat *vf)
    195: {
    196:   PetscScalar    er,ei;
    197:   PetscViewer    viewer = vf->viewer;

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

    224: /*@C
    225:    PEPMonitorAll - Print the current approximate values and
    226:    error estimates at each iteration of the polynomial eigensolver.

    228:    Collective

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

    240:    Options Database Key:
    241: .  -pep_monitor_all - activates `PEPMonitorAll()`

    243:    Note:
    244:    This is not called directly by users, rather one calls `PEPMonitorSet()`, with this
    245:    function as an argument, to cause the monitor to be used during the `PEP` solve.

    247:    Level: intermediate

    249: .seealso: [](ch:pep), `PEPMonitorSet()`, `PEPMonitorFirst()`, `PEPMonitorConverged()`
    250: @*/
    251: PetscErrorCode PEPMonitorAll(PEP pep,PetscInt its,PetscInt nconv,PetscScalar eigr[],PetscScalar eigi[],PetscReal errest[],PetscInt nest,PetscViewerAndFormat *vf)
    252: {
    253:   PetscInt       i;
    254:   PetscScalar    er,ei;
    255:   PetscViewer    viewer = vf->viewer;

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

    283: /*@C
    284:    PEPMonitorConverged - Print the approximate values and
    285:    error estimates as they converge.

    287:    Collective

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

    299:    Options Database Key:
    300: .  -pep_monitor_conv - activates `PEPMonitorConverged()`

    302:    Note:
    303:    This is not called directly by users, rather one calls `PEPMonitorSet()`, with this
    304:    function as an argument, to cause the monitor to be used during the `PEP` solve.

    306:    Level: intermediate

    308: .seealso: [](ch:pep), `PEPMonitorSet()`, `PEPMonitorFirst()`, `PEPMonitorAll()`
    309: @*/
    310: PetscErrorCode PEPMonitorConverged(PEP pep,PetscInt its,PetscInt nconv,PetscScalar eigr[],PetscScalar eigi[],PetscReal errest[],PetscInt nest,PetscViewerAndFormat *vf)
    311: {
    312:   PetscInt       i;
    313:   PetscScalar    er,ei;
    314:   PetscViewer    viewer = vf->viewer;
    315:   SlepcConvMon   ctx;

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

    347: PetscErrorCode PEPMonitorConvergedCreate(PetscViewer viewer,PetscViewerFormat format,void *ctx,PetscViewerAndFormat **vf)
    348: {
    349:   SlepcConvMon   mctx;

    351:   PetscFunctionBegin;
    352:   PetscCall(PetscViewerAndFormatCreate(viewer,format,vf));
    353:   PetscCall(PetscNew(&mctx));
    354:   mctx->ctx = ctx;
    355:   (*vf)->data = (void*)mctx;
    356:   PetscFunctionReturn(PETSC_SUCCESS);
    357: }

    359: PetscErrorCode PEPMonitorConvergedDestroy(PetscViewerAndFormat **vf)
    360: {
    361:   PetscFunctionBegin;
    362:   if (!*vf) PetscFunctionReturn(PETSC_SUCCESS);
    363:   PetscCall(PetscFree((*vf)->data));
    364:   PetscCall(PetscViewerDestroy(&(*vf)->viewer));
    365:   PetscCall(PetscFree(*vf));
    366:   PetscFunctionReturn(PETSC_SUCCESS);
    367: }

    369: /*@C
    370:    PEPMonitorFirstDrawLG - Plots the error estimate of the first unconverged
    371:    approximation at each iteration of the polynomial eigensolver.

    373:    Collective

    375:    Input Parameters:
    376: +  pep    - the polynomial eigensolver context
    377: .  its    - iteration number
    378: .  nconv  - number of converged eigenpairs so far
    379: .  eigr   - real part of the eigenvalues
    380: .  eigi   - imaginary part of the eigenvalues
    381: .  errest - error estimates
    382: .  nest   - number of error estimates to display
    383: -  vf     - viewer and format for monitoring

    385:    Options Database Key:
    386: .  -pep_monitor draw::draw_lg - activates `PEPMonitorFirstDrawLG()`

    388:    Notes:
    389:    This is not called directly by users, rather one calls `PEPMonitorSet()`, with this
    390:    function as an argument, to cause the monitor to be used during the `PEP` solve.

    392:    Call `PEPMonitorFirstDrawLGCreate()` to create the context used with this monitor.

    394:    Level: intermediate

    396: .seealso: [](ch:pep), `PEPMonitorSet()`, `PEPMonitorFirstDrawLGCreate()`
    397: @*/
    398: PetscErrorCode PEPMonitorFirstDrawLG(PEP pep,PetscInt its,PetscInt nconv,PetscScalar eigr[],PetscScalar eigi[],PetscReal errest[],PetscInt nest,PetscViewerAndFormat *vf)
    399: {
    400:   PetscViewer    viewer = vf->viewer;
    401:   PetscDrawLG    lg;
    402:   PetscReal      x,y;

    404:   PetscFunctionBegin;
    407:   PetscCall(PetscViewerPushFormat(viewer,vf->format));
    408:   PetscCall(PetscViewerDrawGetDrawLG(viewer,0,&lg));
    409:   if (its==1) {
    410:     PetscCall(PetscDrawLGReset(lg));
    411:     PetscCall(PetscDrawLGSetDimension(lg,1));
    412:     PetscCall(PetscDrawLGSetLimits(lg,1,1,PetscLog10Real(pep->tol)-2,0.0));
    413:   }
    414:   if (nconv<nest) {
    415:     x = (PetscReal)its;
    416:     if (errest[nconv] > 0.0) y = PetscLog10Real(errest[nconv]);
    417:     else y = 0.0;
    418:     PetscCall(PetscDrawLGAddPoint(lg,&x,&y));
    419:     if (its <= 20 || !(its % 5) || pep->reason) {
    420:       PetscCall(PetscDrawLGDraw(lg));
    421:       PetscCall(PetscDrawLGSave(lg));
    422:     }
    423:   }
    424:   PetscCall(PetscViewerPopFormat(viewer));
    425:   PetscFunctionReturn(PETSC_SUCCESS);
    426: }

    428: /*@C
    429:    PEPMonitorFirstDrawLGCreate - Creates the plotter for the first error estimate.

    431:    Collective

    433:    Input Parameters:
    434: +  viewer - the viewer
    435: .  format - the viewer format
    436: -  ctx    - an optional user context

    438:    Output Parameter:
    439: .  vf     - the viewer and format context

    441:    Level: intermediate

    443: .seealso: [](ch:pep), `PEPMonitorSet()`
    444: @*/
    445: PetscErrorCode PEPMonitorFirstDrawLGCreate(PetscViewer viewer,PetscViewerFormat format,void *ctx,PetscViewerAndFormat **vf)
    446: {
    447:   PetscFunctionBegin;
    448:   PetscCall(PetscViewerAndFormatCreate(viewer,format,vf));
    449:   (*vf)->data = ctx;
    450:   PetscCall(PetscViewerMonitorLGSetUp(viewer,NULL,"First Error Estimate","Log Error Estimate",1,NULL,PETSC_DECIDE,PETSC_DECIDE,400,300));
    451:   PetscFunctionReturn(PETSC_SUCCESS);
    452: }

    454: /*@C
    455:    PEPMonitorAllDrawLG - Plots the error estimate of all unconverged
    456:    approximations at each iteration of the polynomial eigensolver.

    458:    Collective

    460:    Input Parameters:
    461: +  pep    - the polynomial eigensolver context
    462: .  its    - iteration number
    463: .  nconv  - number of converged eigenpairs so far
    464: .  eigr   - real part of the eigenvalues
    465: .  eigi   - imaginary part of the eigenvalues
    466: .  errest - error estimates
    467: .  nest   - number of error estimates to display
    468: -  vf     - viewer and format for monitoring

    470:    Options Database Key:
    471: .  -pep_monitor_all draw::draw_lg - activates `PEPMonitorAllDrawLG()`

    473:    Notes:
    474:    This is not called directly by users, rather one calls `PEPMonitorSet()`, with this
    475:    function as an argument, to cause the monitor to be used during the `PEP` solve.

    477:    Call `PEPMonitorAllDrawLGCreate()` to create the context used with this monitor.

    479:    Level: intermediate

    481: .seealso: [](ch:pep), `PEPMonitorSet()`, `PEPMonitorAllDrawLGCreate()`
    482: @*/
    483: PetscErrorCode PEPMonitorAllDrawLG(PEP pep,PetscInt its,PetscInt nconv,PetscScalar eigr[],PetscScalar eigi[],PetscReal errest[],PetscInt nest,PetscViewerAndFormat *vf)
    484: {
    485:   PetscViewer    viewer = vf->viewer;
    486:   PetscDrawLG    lg;
    487:   PetscInt       i,n = PetscMin(pep->nev,255);
    488:   PetscReal      *x,*y;

    490:   PetscFunctionBegin;
    493:   PetscCall(PetscViewerPushFormat(viewer,vf->format));
    494:   PetscCall(PetscViewerDrawGetDrawLG(viewer,0,&lg));
    495:   if (its==1) {
    496:     PetscCall(PetscDrawLGReset(lg));
    497:     PetscCall(PetscDrawLGSetDimension(lg,n));
    498:     PetscCall(PetscDrawLGSetLimits(lg,1,1,PetscLog10Real(pep->tol)-2,0.0));
    499:   }
    500:   PetscCall(PetscMalloc2(n,&x,n,&y));
    501:   for (i=0;i<n;i++) {
    502:     x[i] = (PetscReal)its;
    503:     if (i < nest && errest[i] > 0.0) y[i] = PetscLog10Real(errest[i]);
    504:     else y[i] = 0.0;
    505:   }
    506:   PetscCall(PetscDrawLGAddPoint(lg,x,y));
    507:   if (its <= 20 || !(its % 5) || pep->reason) {
    508:     PetscCall(PetscDrawLGDraw(lg));
    509:     PetscCall(PetscDrawLGSave(lg));
    510:   }
    511:   PetscCall(PetscFree2(x,y));
    512:   PetscCall(PetscViewerPopFormat(viewer));
    513:   PetscFunctionReturn(PETSC_SUCCESS);
    514: }

    516: /*@C
    517:    PEPMonitorAllDrawLGCreate - Creates the plotter for all the error estimates.

    519:    Collective

    521:    Input Parameters:
    522: +  viewer - the viewer
    523: .  format - the viewer format
    524: -  ctx    - an optional user context

    526:    Output Parameter:
    527: .  vf     - the viewer and format context

    529:    Level: intermediate

    531: .seealso: [](ch:pep), `PEPMonitorSet()`
    532: @*/
    533: PetscErrorCode PEPMonitorAllDrawLGCreate(PetscViewer viewer,PetscViewerFormat format,void *ctx,PetscViewerAndFormat **vf)
    534: {
    535:   PetscFunctionBegin;
    536:   PetscCall(PetscViewerAndFormatCreate(viewer,format,vf));
    537:   (*vf)->data = ctx;
    538:   PetscCall(PetscViewerMonitorLGSetUp(viewer,NULL,"All Error Estimates","Log Error Estimate",1,NULL,PETSC_DECIDE,PETSC_DECIDE,400,300));
    539:   PetscFunctionReturn(PETSC_SUCCESS);
    540: }

    542: /*@C
    543:    PEPMonitorConvergedDrawLG - Plots the number of converged eigenvalues
    544:    at each iteration of the polynomial eigensolver.

    546:    Collective

    548:    Input Parameters:
    549: +  pep    - the polynomial eigensolver context
    550: .  its    - iteration number
    551: .  nconv  - number of converged eigenpairs so far
    552: .  eigr   - real part of the eigenvalues
    553: .  eigi   - imaginary part of the eigenvalues
    554: .  errest - error estimates
    555: .  nest   - number of error estimates to display
    556: -  vf     - viewer and format for monitoring

    558:    Options Database Key:
    559: .  -pep_monitor_conv draw::draw_lg - activates `PEPMonitorConvergedDrawLG()`

    561:    Notes:
    562:    This is not called directly by users, rather one calls `PEPMonitorSet()`, with this
    563:    function as an argument, to cause the monitor to be used during the `PEP` solve.

    565:    Call `PEPMonitorConvergedDrawLGCreate()` to create the context used with this monitor.

    567:    Level: intermediate

    569: .seealso: [](ch:pep), `PEPMonitorSet()`, `PEPMonitorConvergedDrawLGCreate()`
    570: @*/
    571: PetscErrorCode PEPMonitorConvergedDrawLG(PEP pep,PetscInt its,PetscInt nconv,PetscScalar eigr[],PetscScalar eigi[],PetscReal errest[],PetscInt nest,PetscViewerAndFormat *vf)
    572: {
    573:   PetscViewer      viewer = vf->viewer;
    574:   PetscDrawLG      lg;
    575:   PetscReal        x,y;

    577:   PetscFunctionBegin;
    580:   PetscCall(PetscViewerPushFormat(viewer,vf->format));
    581:   PetscCall(PetscViewerDrawGetDrawLG(viewer,0,&lg));
    582:   if (its==1) {
    583:     PetscCall(PetscDrawLGReset(lg));
    584:     PetscCall(PetscDrawLGSetDimension(lg,1));
    585:     PetscCall(PetscDrawLGSetLimits(lg,1,1,0,pep->nev));
    586:   }
    587:   x = (PetscReal)its;
    588:   y = (PetscReal)pep->nconv;
    589:   PetscCall(PetscDrawLGAddPoint(lg,&x,&y));
    590:   if (its <= 20 || !(its % 5) || pep->reason) {
    591:     PetscCall(PetscDrawLGDraw(lg));
    592:     PetscCall(PetscDrawLGSave(lg));
    593:   }
    594:   PetscCall(PetscViewerPopFormat(viewer));
    595:   PetscFunctionReturn(PETSC_SUCCESS);
    596: }

    598: /*@C
    599:    PEPMonitorConvergedDrawLGCreate - Creates the plotter for the convergence history.

    601:    Collective

    603:    Input Parameters:
    604: +  viewer - the viewer
    605: .  format - the viewer format
    606: -  ctx    - an optional user context

    608:    Output Parameter:
    609: .  vf     - the viewer and format context

    611:    Level: intermediate

    613: .seealso: [](ch:pep), `PEPMonitorSet()`
    614: @*/
    615: PetscErrorCode PEPMonitorConvergedDrawLGCreate(PetscViewer viewer,PetscViewerFormat format,void *ctx,PetscViewerAndFormat **vf)
    616: {
    617:   SlepcConvMon   mctx;

    619:   PetscFunctionBegin;
    620:   PetscCall(PetscViewerAndFormatCreate(viewer,format,vf));
    621:   PetscCall(PetscNew(&mctx));
    622:   mctx->ctx = ctx;
    623:   (*vf)->data = (void*)mctx;
    624:   PetscCall(PetscViewerMonitorLGSetUp(viewer,NULL,"Convergence History","Number Converged",1,NULL,PETSC_DECIDE,PETSC_DECIDE,400,300));
    625:   PetscFunctionReturn(PETSC_SUCCESS);
    626: }