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: .  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: +  -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,PetscCtx ctx,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,ctx,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]    = ctx;
     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,PetscCtxRt 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:    Notes:
    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:    Call `PEPMonitorConvergedCreate()` to create the context used with this monitor.

    308:    Level: intermediate

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

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

    348: /*@C
    349:    PEPMonitorConvergedCreate - Creates the context for the convergence history monitor.

    351:    Collective

    353:    Input Parameters:
    354: +  viewer - the viewer
    355: .  format - the viewer format
    356: -  ctx    - an optional user context

    358:    Output Parameter:
    359: .  vf     - the viewer and format context

    361:    Level: intermediate

    363: .seealso: [](ch:pep), `PEPMonitorSet()`
    364: @*/
    365: PetscErrorCode PEPMonitorConvergedCreate(PetscViewer viewer,PetscViewerFormat format,PetscCtx ctx,PetscViewerAndFormat **vf)
    366: {
    367:   PetscInt *oldnconv;

    369:   PetscFunctionBegin;
    370:   PetscCall(PetscViewerAndFormatCreate(viewer,format,vf));
    371:   PetscCall(PetscNew(&oldnconv));
    372:   (*vf)->data = (void*)oldnconv;
    373:   (*vf)->data_destroy = PetscCtxDestroyDefault;
    374:   PetscFunctionReturn(PETSC_SUCCESS);
    375: }

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

    381:    Collective

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

    393:    Options Database Key:
    394: .  -pep_monitor draw::draw_lg - activates `PEPMonitorFirstDrawLG()`

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

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

    402:    Level: intermediate

    404: .seealso: [](ch:pep), `PEPMonitorSet()`, `PEPMonitorFirstDrawLGCreate()`
    405: @*/
    406: PetscErrorCode PEPMonitorFirstDrawLG(PEP pep,PetscInt its,PetscInt nconv,PetscScalar eigr[],PetscScalar eigi[],PetscReal errest[],PetscInt nest,PetscViewerAndFormat *vf)
    407: {
    408:   PetscViewer    viewer = vf->viewer;
    409:   PetscDrawLG    lg;
    410:   PetscReal      x,y;

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

    436: /*@C
    437:    PEPMonitorFirstDrawLGCreate - Creates the plotter for the first error estimate.

    439:    Collective

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

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

    449:    Level: intermediate

    451: .seealso: [](ch:pep), `PEPMonitorSet()`
    452: @*/
    453: PetscErrorCode PEPMonitorFirstDrawLGCreate(PetscViewer viewer,PetscViewerFormat format,void *ctx,PetscViewerAndFormat **vf)
    454: {
    455:   PetscFunctionBegin;
    456:   PetscCall(PetscViewerAndFormatCreate(viewer,format,vf));
    457:   (*vf)->data = ctx;
    458:   PetscCall(PetscViewerMonitorLGSetUp(viewer,NULL,"First Error Estimate","Log Error Estimate",1,NULL,PETSC_DECIDE,PETSC_DECIDE,400,300));
    459:   PetscFunctionReturn(PETSC_SUCCESS);
    460: }

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

    466:    Collective

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

    478:    Options Database Key:
    479: .  -pep_monitor_all draw::draw_lg - activates `PEPMonitorAllDrawLG()`

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

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

    487:    Level: intermediate

    489: .seealso: [](ch:pep), `PEPMonitorSet()`, `PEPMonitorAllDrawLGCreate()`
    490: @*/
    491: PetscErrorCode PEPMonitorAllDrawLG(PEP pep,PetscInt its,PetscInt nconv,PetscScalar eigr[],PetscScalar eigi[],PetscReal errest[],PetscInt nest,PetscViewerAndFormat *vf)
    492: {
    493:   PetscViewer    viewer = vf->viewer;
    494:   PetscDrawLG    lg;
    495:   PetscInt       i,n = PetscMin(pep->nev,255);
    496:   PetscReal      *x,*y;

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

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

    527:    Collective

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

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

    537:    Level: intermediate

    539: .seealso: [](ch:pep), `PEPMonitorSet()`
    540: @*/
    541: PetscErrorCode PEPMonitorAllDrawLGCreate(PetscViewer viewer,PetscViewerFormat format,void *ctx,PetscViewerAndFormat **vf)
    542: {
    543:   PetscFunctionBegin;
    544:   PetscCall(PetscViewerAndFormatCreate(viewer,format,vf));
    545:   (*vf)->data = ctx;
    546:   PetscCall(PetscViewerMonitorLGSetUp(viewer,NULL,"All Error Estimates","Log Error Estimate",1,NULL,PETSC_DECIDE,PETSC_DECIDE,400,300));
    547:   PetscFunctionReturn(PETSC_SUCCESS);
    548: }

    550: /*@C
    551:    PEPMonitorConvergedDrawLG - Plots the number of converged eigenvalues
    552:    at each iteration of the polynomial eigensolver.

    554:    Collective

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

    566:    Options Database Key:
    567: .  -pep_monitor_conv draw::draw_lg - activates `PEPMonitorConvergedDrawLG()`

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

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

    575:    Level: intermediate

    577: .seealso: [](ch:pep), `PEPMonitorSet()`, `PEPMonitorConvergedDrawLGCreate()`
    578: @*/
    579: PetscErrorCode PEPMonitorConvergedDrawLG(PEP pep,PetscInt its,PetscInt nconv,PetscScalar eigr[],PetscScalar eigi[],PetscReal errest[],PetscInt nest,PetscViewerAndFormat *vf)
    580: {
    581:   PetscViewer      viewer = vf->viewer;
    582:   PetscDrawLG      lg;
    583:   PetscReal        x,y;

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

    606: /*@C
    607:    PEPMonitorConvergedDrawLGCreate - Creates the plotter for the convergence history.

    609:    Collective

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

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

    619:    Level: intermediate

    621: .seealso: [](ch:pep), `PEPMonitorSet()`
    622: @*/
    623: PetscErrorCode PEPMonitorConvergedDrawLGCreate(PetscViewer viewer,PetscViewerFormat format,void *ctx,PetscViewerAndFormat **vf)
    624: {
    625:   PetscInt *oldnconv;

    627:   PetscFunctionBegin;
    628:   PetscCall(PetscViewerAndFormatCreate(viewer,format,vf));
    629:   PetscCall(PetscNew(&oldnconv));
    630:   (*vf)->data = (void*)oldnconv;
    631:   (*vf)->data_destroy = PetscCtxDestroyDefault;
    632:   PetscCall(PetscViewerMonitorLGSetUp(viewer,NULL,"Convergence History","Number Converged",1,NULL,PETSC_DECIDE,PETSC_DECIDE,400,300));
    633:   PetscFunctionReturn(PETSC_SUCCESS);
    634: }