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

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

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

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

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

     33:    Logically Collective

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

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

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

     58:    Several different monitoring routines may be set by calling `MFNMonitorSet()` 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:mfn), `MFNMonitorDefault()`, `MFNMonitorDefaultDrawLG()`, `MFNMonitorCancel()`
     67: @*/
     68: PetscErrorCode MFNMonitorSet(MFN mfn,MFNMonitorFn *monitor,void *mctx,PetscCtxDestroyFn *monitordestroy)
     69: {
     70:   PetscInt  i;
     71:   PetscBool identical;

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

     86: /*@
     87:    MFNMonitorCancel - Clears all monitors for an `MFN` object.

     89:    Logically Collective

     91:    Input Parameter:
     92: .  mfn - the matrix function solver context

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

     98:    Level: intermediate

    100: .seealso: [](ch:mfn), `MFNMonitorSet()`
    101: @*/
    102: PetscErrorCode MFNMonitorCancel(MFN mfn)
    103: {
    104:   PetscInt       i;

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

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

    119:    Not Collective

    121:    Input Parameter:
    122: .  mfn - the matrix function solver context

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

    127:    Level: intermediate

    129: .seealso: [](ch:mfn), `MFNMonitorSet()`
    130: @*/
    131: PetscErrorCode MFNGetMonitorContext(MFN mfn,void *ctx)
    132: {
    133:   PetscFunctionBegin;
    135:   *(void**)ctx = mfn->monitorcontext[0];
    136:   PetscFunctionReturn(PETSC_SUCCESS);
    137: }

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

    143:    Collective

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

    151:    Options Database Key:
    152: .  -mfn_monitor - activates `MFNMonitorDefault()`

    154:    Level: intermediate

    156: .seealso: [](ch:mfn), `MFNMonitorSet()`
    157: @*/
    158: PetscErrorCode MFNMonitorDefault(MFN mfn,PetscInt its,PetscReal errest,PetscViewerAndFormat *vf)
    159: {
    160:   PetscViewer    viewer = vf->viewer;

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

    174: /*@C
    175:    MFNMonitorDefaultDrawLG - Plots the error estimate of the current approximation at each
    176:    iteration of the matrix function solver.

    178:    Collective

    180:    Input Parameters:
    181: +  mfn    - the matrix function solver context
    182: .  its    - iteration number
    183: .  errest - error estimate
    184: -  vf     - viewer and format for monitoring

    186:    Options Database Key:
    187: .  -mfn_monitor draw::draw_lg - activates `MFNMonitorDefaultDrawLG()`

    189:    Notes:
    190:    This is not called directly by users, rather one calls `MFNMonitorSet()`, with this
    191:    function as an argument, to cause the monitor to be used during the `MFN` solve.

    193:    Call `MFNMonitorDefaultDrawLGCreate()` to create the context used with this monitor.

    195:    Level: intermediate

    197: .seealso: [](ch:mfn), `MFNMonitorSet()`, `MFNMonitorDefaultDrawLGCreate()`
    198: @*/
    199: PetscErrorCode MFNMonitorDefaultDrawLG(MFN mfn,PetscInt its,PetscReal errest,PetscViewerAndFormat *vf)
    200: {
    201:   PetscViewer    viewer = vf->viewer;
    202:   PetscDrawLG    lg;
    203:   PetscReal      x,y;

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

    227: /*@C
    228:    MFNMonitorDefaultDrawLGCreate - Creates the plotter for the error estimate.

    230:    Collective

    232:    Input Parameters:
    233: +  viewer - the viewer
    234: .  format - the viewer format
    235: -  ctx    - an optional user context

    237:    Output Parameter:
    238: .  vf     - the viewer and format context

    240:    Level: intermediate

    242: .seealso: [](ch:mfn), `MFNMonitorSet()`
    243: @*/
    244: PetscErrorCode MFNMonitorDefaultDrawLGCreate(PetscViewer viewer,PetscViewerFormat format,void *ctx,PetscViewerAndFormat **vf)
    245: {
    246:   PetscFunctionBegin;
    247:   PetscCall(PetscViewerAndFormatCreate(viewer,format,vf));
    248:   (*vf)->data = ctx;
    249:   PetscCall(PetscViewerMonitorLGSetUp(viewer,NULL,"Error Estimate","Log Error Estimate",1,NULL,PETSC_DECIDE,PETSC_DECIDE,400,300));
    250:   PetscFunctionReturn(PETSC_SUCCESS);
    251: }