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

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

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

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

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

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

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

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

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

     71:    Level: intermediate

     73: .seealso: [](ch:eps), `EPSMonitorFirst()`, `EPSMonitorAll()`, `EPSMonitorConverged()`, `EPSMonitorFirstDrawLG()`, `EPSMonitorAllDrawLG()`, `EPSMonitorConvergedDrawLG()`, `EPSMonitorCancel()`
     74: @*/
     75: PetscErrorCode EPSMonitorSet(EPS eps,EPSMonitorFn *monitor,void *mctx,PetscCtxDestroyFn *monitordestroy)
     76: {
     77:   PetscInt  i;
     78:   PetscBool identical;

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

     93: /*@
     94:    EPSMonitorCancel - Clears all monitors for an `EPS` object.

     96:    Logically Collective

     98:    Input Parameter:
     99: .  eps - the linear eigensolver context

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

    105:    Level: intermediate

    107: .seealso: [](ch:eps), `EPSMonitorSet()`
    108: @*/
    109: PetscErrorCode EPSMonitorCancel(EPS eps)
    110: {
    111:   PetscInt       i;

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

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

    126:    Not Collective

    128:    Input Parameter:
    129: .  eps - the linear eigensolver context

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

    134:    Level: intermediate

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

    146: static inline PetscErrorCode EPSMonitorPrintEval(EPS eps,PetscViewer viewer,PetscScalar er,PetscScalar ei)
    147: {
    148:   PetscFunctionBegin;
    149:   if (eps->problem_type==EPS_HEP || eps->problem_type==EPS_GHEP || eps->problem_type==EPS_BSE) PetscCall(PetscViewerASCIIPrintf(viewer," %g",(double)PetscRealPart(er)));
    150:   else {
    151: #if defined(PETSC_USE_COMPLEX)
    152:     PetscCall(PetscViewerASCIIPrintf(viewer," %g%+gi",(double)PetscRealPart(er),(double)PetscImaginaryPart(er)));
    153: #else
    154:     PetscCall(PetscViewerASCIIPrintf(viewer," %g",(double)er));
    155:     if (ei!=0.0) PetscCall(PetscViewerASCIIPrintf(viewer,"%+gi",(double)ei));
    156: #endif
    157:   }
    158:   PetscFunctionReturn(PETSC_SUCCESS);
    159: }

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

    165:    Collective

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

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

    180:    Note:
    181:    This is not called directly by users, rather one calls `EPSMonitorSet()`, with this
    182:    function as an argument, to cause the monitor to be used during the `EPS` solve.

    184:    Level: intermediate

    186: .seealso: [](ch:eps), `EPSMonitorSet()`, `EPSMonitorAll()`, `EPSMonitorConverged()`
    187: @*/
    188: PetscErrorCode EPSMonitorFirst(EPS eps,PetscInt its,PetscInt nconv,PetscScalar eigr[],PetscScalar eigi[],PetscReal errest[],PetscInt nest,PetscViewerAndFormat *vf)
    189: {
    190:   PetscScalar    er,ei;
    191:   PetscViewer    viewer = vf->viewer;

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

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

    217:    Collective

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

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

    232:    Note:
    233:    This is not called directly by users, rather one calls `EPSMonitorSet()`, with this
    234:    function as an argument, to cause the monitor to be used during the `EPS` solve.

    236:    Level: intermediate

    238: .seealso: [](ch:eps), `EPSMonitorSet()`, `EPSMonitorFirst()`, `EPSMonitorConverged()`
    239: @*/
    240: PetscErrorCode EPSMonitorAll(EPS eps,PetscInt its,PetscInt nconv,PetscScalar eigr[],PetscScalar eigi[],PetscReal errest[],PetscInt nest,PetscViewerAndFormat *vf)
    241: {
    242:   PetscInt       i;
    243:   PetscScalar    er,ei;
    244:   PetscViewer    viewer = vf->viewer;

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

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

    271:    Collective

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

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

    286:    Note:
    287:    This is not called directly by users, rather one calls `EPSMonitorSet()`, with this
    288:    function as an argument, to cause the monitor to be used during the `EPS` solve.

    290:    Level: intermediate

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

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

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

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

    338: PetscErrorCode EPSMonitorConvergedDestroy(PetscViewerAndFormat **vf)
    339: {
    340:   PetscFunctionBegin;
    341:   if (!*vf) PetscFunctionReturn(PETSC_SUCCESS);
    342:   PetscCall(PetscFree((*vf)->data));
    343:   PetscCall(PetscViewerDestroy(&(*vf)->viewer));
    344:   PetscCall(PetscFree(*vf));
    345:   PetscFunctionReturn(PETSC_SUCCESS);
    346: }

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

    352:    Collective

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

    364:    Options Database Key:
    365: .  -eps_monitor draw::draw_lg - activates `EPSMonitorFirstDrawLG()`

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

    371:    Call `EPSMonitorFirstDrawLGCreate()` to create the context used with this monitor.

    373:    Level: intermediate

    375: .seealso: [](ch:eps), `EPSMonitorSet()`, `EPSMonitorFirstDrawLGCreate()`
    376: @*/
    377: PetscErrorCode EPSMonitorFirstDrawLG(EPS eps,PetscInt its,PetscInt nconv,PetscScalar eigr[],PetscScalar eigi[],PetscReal errest[],PetscInt nest,PetscViewerAndFormat *vf)
    378: {
    379:   PetscViewer    viewer = vf->viewer;
    380:   PetscDrawLG    lg;
    381:   PetscReal      x,y;

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

    407: /*@C
    408:    EPSMonitorFirstDrawLGCreate - Creates the plotter for the first error estimate.

    410:    Collective

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

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

    420:    Level: intermediate

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

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

    437:    Collective

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

    449:    Options Database Key:
    450: .  -eps_monitor_all draw::draw_lg - activates `EPSMonitorAllDrawLG()`

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

    456:    Call `EPSMonitorAllDrawLGCreate()` to create the context used with this monitor.

    458:    Level: intermediate

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

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

    495: /*@C
    496:    EPSMonitorAllDrawLGCreate - Creates the plotter for all the error estimates.

    498:    Collective

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

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

    508:    Level: intermediate

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

    521: /*@C
    522:    EPSMonitorConvergedDrawLG - Plots the number of converged eigenvalues
    523:    at each iteration of the eigensolver.

    525:    Collective

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

    537:    Options Database Key:
    538: .  -eps_monitor_conv draw::draw_lg - activates `EPSMonitorConvergedDrawLG()`

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

    544:    Call `EPSMonitorConvergedDrawLGCreate()` to create the context used with this monitor.

    546:    Level: intermediate

    548: .seealso: [](ch:eps), `EPSMonitorSet()`, `EPSMonitorConvergedDrawLGCreate()`
    549: @*/
    550: PetscErrorCode EPSMonitorConvergedDrawLG(EPS eps,PetscInt its,PetscInt nconv,PetscScalar eigr[],PetscScalar eigi[],PetscReal errest[],PetscInt nest,PetscViewerAndFormat *vf)
    551: {
    552:   PetscViewer      viewer = vf->viewer;
    553:   PetscDrawLG      lg;
    554:   PetscReal        x,y;

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

    577: /*@C
    578:    EPSMonitorConvergedDrawLGCreate - Creates the plotter for the convergence history.

    580:    Collective

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

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

    590:    Level: intermediate

    592: .seealso: [](ch:eps), `EPSMonitorSet()`
    593: @*/
    594: PetscErrorCode EPSMonitorConvergedDrawLGCreate(PetscViewer viewer,PetscViewerFormat format,void *ctx,PetscViewerAndFormat **vf)
    595: {
    596:   SlepcConvMon   mctx;

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