Date: 2026-05-01T10:02:39+00:00

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

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

     17: /*
     18:    Runs the user provided monitor routines, if any.
     19: */
     20: PetscErrorCode LMEMonitor(LME lme,PetscInt it,PetscReal errest)
     21: {
     22:   PetscInt       i,n = lme->numbermonitors;

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

     29: /*@C
     30:    LMEMonitorSet - Sets an ADDITIONAL function to be called at every
     31:    iteration to monitor convergence.

     33:    Logically Collective

     35:    Input Parameters:
     36: +  lme            - the linear matrix equation solver context
     37: .  monitor        - pointer to function (if this is `NULL`, it turns off monitoring),
     38:                     see `LMEMonitorFn`
     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: +  -lme_monitor               - print the error estimate
     46: .  -lme_monitor draw::draw_lg - sets line graph monitor for the error estimate
     47: -  -lme_monitor_cancel        - cancels all monitors that have been hardwired into
     48:                                 a code by calls to `LMEMonitorSet()`, but does not cancel
     49:                                 those set via the options database

     51:    Notes:
     52:    The options database option `-lme_monitor` and related options are the easiest way
     53:    to turn on `LME` iteration monitoring.

     55:    `LMEMonitorRegister()` provides a way to associate an options database key with `LME`
     56:    monitor function.

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

     61:    Fortran Note:
     62:    Only a single monitor function can be set for each `LME` object.

     64:    Level: intermediate

     66: .seealso: [](ch:lme), `LMEMonitorDefault()`, `LMEMonitorDefaultDrawLG()`, `LMEMonitorCancel()`
     67: @*/
     68: PetscErrorCode LMEMonitorSet(LME lme,LMEMonitorFn *monitor,PetscCtx ctx,PetscCtxDestroyFn *monitordestroy)
     69: {
     70:   PetscInt  i;
     71:   PetscBool identical;

     73:   PetscFunctionBegin;
     75:   for (i=0;i<lme->numbermonitors;i++) {
     76:     PetscCall(PetscMonitorCompare((PetscErrorCode(*)(void))(PetscVoidFn*)monitor,ctx,monitordestroy,(PetscErrorCode (*)(void))(PetscVoidFn*)lme->monitor[i],lme->monitorcontext[i],lme->monitordestroy[i],&identical));
     77:     if (identical) PetscFunctionReturn(PETSC_SUCCESS);
     78:   }
     79:   PetscCheck(lme->numbermonitors<MAXLMEMONITORS,PetscObjectComm((PetscObject)lme),PETSC_ERR_ARG_OUTOFRANGE,"Too many LME monitors set");
     80:   lme->monitor[lme->numbermonitors]           = monitor;
     81:   lme->monitorcontext[lme->numbermonitors]    = ctx;
     82:   lme->monitordestroy[lme->numbermonitors++]  = monitordestroy;
     83:   PetscFunctionReturn(PETSC_SUCCESS);
     84: }

     86: /*@
     87:    LMEMonitorCancel - Clears all monitors for an `LME` object.

     89:    Logically Collective

     91:    Input Parameter:
     92: .  lme - the linear matrix equation solver context

     94:    Options Database Key:
     95: .  -lme_monitor_cancel - cancels all monitors that have been hardwired into a code by calls to
     96:                          `LMEMonitorSet()`, but does not cancel those set via the options database.

     98:    Level: intermediate

    100: .seealso: [](ch:lme), `LMEMonitorSet()`
    101: @*/
    102: PetscErrorCode LMEMonitorCancel(LME lme)
    103: {
    104:   PetscInt       i;

    106:   PetscFunctionBegin;
    108:   for (i=0; i<lme->numbermonitors; i++) {
    109:     if (lme->monitordestroy[i]) PetscCall((*lme->monitordestroy[i])(&lme->monitorcontext[i]));
    110:   }
    111:   lme->numbermonitors = 0;
    112:   PetscFunctionReturn(PETSC_SUCCESS);
    113: }

    115: /*@C
    116:    LMEGetMonitorContext - Gets the monitor context, as set by
    117:    `LMEMonitorSet()` for the FIRST monitor only.

    119:    Not Collective

    121:    Input Parameter:
    122: .  lme - the linear matrix equation solver context

    124:    Output Parameter:
    125: .  ctx - monitor context

    127:    Level: intermediate

    129: .seealso: [](ch:lme), `LMEMonitorSet()`
    130: @*/
    131: PetscErrorCode LMEGetMonitorContext(LME lme,PetscCtxRt ctx)
    132: {
    133:   PetscFunctionBegin;
    135:   *(void**)ctx = lme->monitorcontext[0];
    136:   PetscFunctionReturn(PETSC_SUCCESS);
    137: }

    139: /*@C
    140:    LMEMonitorDefault - Print the error estimate of the current approximation at each
    141:    iteration of the linear matrix equation solver.

    143:    Collective

    145:    Input Parameters:
    146: +  lme    - the linear matrix equation solver context
    147: .  its    - iteration number
    148: .  errest - error estimate
    149: -  vf     - viewer and format for monitoring

    151:    Options Database Key:
    152: .  -lme_monitor - activates `LMEMonitorDefault()`

    154:    Note:
    155:    This is not called directly by users, rather one calls `LMEMonitorSet()`, with this
    156:    function as an argument, to cause the monitor to be used during the `LME` solve.

    158:    Level: intermediate

    160: .seealso: [](ch:lme), `LMEMonitorSet()`
    161: @*/
    162: PetscErrorCode LMEMonitorDefault(LME lme,PetscInt its,PetscReal errest,PetscViewerAndFormat *vf)
    163: {
    164:   PetscViewer    viewer = vf->viewer;

    166:   PetscFunctionBegin;
    169:   PetscCall(PetscViewerPushFormat(viewer,vf->format));
    170:   PetscCall(PetscViewerASCIIAddTab(viewer,((PetscObject)lme)->tablevel));
    171:   if (its == 1 && ((PetscObject)lme)->prefix) PetscCall(PetscViewerASCIIPrintf(viewer,"  Error estimates for %s solve.\n",((PetscObject)lme)->prefix));
    172:   PetscCall(PetscViewerASCIIPrintf(viewer,"%3" PetscInt_FMT " LME Error estimate %14.12e\n",its,(double)errest));
    173:   PetscCall(PetscViewerASCIISubtractTab(viewer,((PetscObject)lme)->tablevel));
    174:   PetscCall(PetscViewerPopFormat(viewer));
    175:   PetscFunctionReturn(PETSC_SUCCESS);
    176: }

    178: /*@C
    179:    LMEMonitorDefaultDrawLG - Plots the error estimate of the current approximation at each
    180:    iteration of the linear matrix equation solver.

    182:    Collective

    184:    Input Parameters:
    185: +  lme    - the linear matrix equation solver context
    186: .  its    - iteration number
    187: .  errest - error estimate
    188: -  vf     - viewer and format for monitoring

    190:    Options Database Key:
    191: .  -lme_monitor draw::draw_lg - activates `LMEMonitorDefaultDrawLG()`

    193:    Notes:
    194:    This is not called directly by users, rather one calls `LMEMonitorSet()`, with this
    195:    function as an argument, to cause the monitor to be used during the `LME` solve.

    197:    Call `LMEMonitorDefaultDrawLGCreate()` to create the context used with this monitor.

    199:    Level: intermediate

    201: .seealso: [](ch:lme), `LMEMonitorSet()`, `LMEMonitorDefaultDrawLGCreate()`
    202: @*/
    203: PetscErrorCode LMEMonitorDefaultDrawLG(LME lme,PetscInt its,PetscReal errest,PetscViewerAndFormat *vf)
    204: {
    205:   PetscViewer    viewer = vf->viewer;
    206:   PetscDrawLG    lg;
    207:   PetscReal      x,y;

    209:   PetscFunctionBegin;
    212:   PetscCall(PetscViewerPushFormat(viewer,vf->format));
    213:   PetscCall(PetscViewerDrawGetDrawLG(viewer,0,&lg));
    214:   if (its==1) {
    215:     PetscCall(PetscDrawLGReset(lg));
    216:     PetscCall(PetscDrawLGSetDimension(lg,1));
    217:     PetscCall(PetscDrawLGSetLimits(lg,1,1.0,PetscLog10Real(lme->tol)-2,0.0));
    218:   }
    219:   x = (PetscReal)its;
    220:   if (errest > 0.0) y = PetscLog10Real(errest);
    221:   else y = 0.0;
    222:   PetscCall(PetscDrawLGAddPoint(lg,&x,&y));
    223:   if (its <= 20 || !(its % 5) || lme->reason) {
    224:     PetscCall(PetscDrawLGDraw(lg));
    225:     PetscCall(PetscDrawLGSave(lg));
    226:   }
    227:   PetscCall(PetscViewerPopFormat(viewer));
    228:   PetscFunctionReturn(PETSC_SUCCESS);
    229: }

    231: /*@C
    232:    LMEMonitorDefaultDrawLGCreate - Creates the plotter for the error estimate.

    234:    Collective

    236:    Input Parameters:
    237: +  viewer - the viewer
    238: .  format - the viewer format
    239: -  ctx    - an optional user context

    241:    Output Parameter:
    242: .  vf     - the viewer and format context

    244:    Level: intermediate

    246: .seealso: [](ch:lme), `LMEMonitorSet()`
    247: @*/
    248: PetscErrorCode LMEMonitorDefaultDrawLGCreate(PetscViewer viewer,PetscViewerFormat format,void *ctx,PetscViewerAndFormat **vf)
    249: {
    250:   PetscFunctionBegin;
    251:   PetscCall(PetscViewerAndFormatCreate(viewer,format,vf));
    252:   (*vf)->data = ctx;
    253:   PetscCall(PetscViewerMonitorLGSetUp(viewer,NULL,"Error Estimate","Log Error Estimate",1,NULL,PETSC_DECIDE,PETSC_DECIDE,400,300));
    254:   PetscFunctionReturn(PETSC_SUCCESS);
    255: }