Date: 2026-03-31T13:23:05+00:00

Actual source code: mfnbasic.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:    Basic MFN routines
     12: */

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

     16: /* Logging support */
     17: PetscClassId      MFN_CLASSID = 0;
     18: PetscLogEvent     MFN_SetUp = 0,MFN_Solve = 0;

     20: /* List of registered MFN routines */
     21: PetscFunctionList MFNList = NULL;
     22: PetscBool         MFNRegisterAllCalled = PETSC_FALSE;

     24: /* List of registered MFN monitors */
     25: PetscFunctionList MFNMonitorList              = NULL;
     26: PetscFunctionList MFNMonitorCreateList        = NULL;
     27: PetscFunctionList MFNMonitorDestroyList       = NULL;
     28: PetscBool         MFNMonitorRegisterAllCalled = PETSC_FALSE;

     30: /*@
     31:    MFNView - Prints the `MFN` data structure.

     33:    Collective

     35:    Input Parameters:
     36: +  mfn - the matrix function solver context
     37: -  viewer - optional visualization context

     39:    Options Database Key:
     40: .  -mfn_view - calls `MFNView()` at end of `MFNSolve()`

     42:    Notes:
     43:    The available visualization contexts include
     44: +     `PETSC_VIEWER_STDOUT_SELF` - standard output (default)
     45: -     `PETSC_VIEWER_STDOUT_WORLD` - synchronized standard output where only the
     46:          first process opens the file; all other processes send their data to the
     47:          first one to print

     49:    The user can open an alternative visualization context with `PetscViewerASCIIOpen()`
     50:    to output to a specified file.

     52:    Level: beginner

     54: .seealso: [](ch:mfn), `MFNCreate()`, `MFNViewFromOptions()`
     55: @*/
     56: PetscErrorCode MFNView(MFN mfn,PetscViewer viewer)
     57: {
     58:   PetscBool      isascii;

     60:   PetscFunctionBegin;
     62:   if (!viewer) PetscCall(PetscViewerASCIIGetStdout(PetscObjectComm((PetscObject)mfn),&viewer));
     64:   PetscCheckSameComm(mfn,1,viewer,2);

     66:   PetscCall(PetscObjectTypeCompare((PetscObject)viewer,PETSCVIEWERASCII,&isascii));
     67:   if (isascii) {
     68:     PetscCall(PetscObjectPrintClassNamePrefixType((PetscObject)mfn,viewer));
     69:     PetscCall(PetscViewerASCIIPushTab(viewer));
     70:     PetscTryTypeMethod(mfn,view,viewer);
     71:     PetscCall(PetscViewerASCIIPopTab(viewer));
     72:     PetscCall(PetscViewerASCIIPrintf(viewer,"  number of column vectors (ncv): %" PetscInt_FMT "\n",mfn->ncv));
     73:     PetscCall(PetscViewerASCIIPrintf(viewer,"  maximum number of iterations: %" PetscInt_FMT "\n",mfn->max_it));
     74:     PetscCall(PetscViewerASCIIPrintf(viewer,"  tolerance: %g\n",(double)mfn->tol));
     75:   } else PetscTryTypeMethod(mfn,view,viewer);
     76:   PetscCall(PetscViewerPushFormat(viewer,PETSC_VIEWER_ASCII_INFO));
     77:   if (!mfn->V) PetscCall(MFNGetFN(mfn,&mfn->fn));
     78:   PetscCall(FNView(mfn->fn,viewer));
     79:   if (!mfn->V) PetscCall(MFNGetBV(mfn,&mfn->V));
     80:   PetscCall(BVView(mfn->V,viewer));
     81:   PetscCall(PetscViewerPopFormat(viewer));
     82:   PetscFunctionReturn(PETSC_SUCCESS);
     83: }

     85: /*@
     86:    MFNViewFromOptions - View (print) an `MFN` object based on values in the options database.

     88:    Collective

     90:    Input Parameters:
     91: +  mfn  - the matrix function solver context
     92: .  obj  - optional object that provides the options prefix used to query the options database
     93: -  name - command line option

     95:    Level: intermediate

     97: .seealso: [](ch:mfn), `MFNView()`, `MFNCreate()`, `PetscObjectViewFromOptions()`
     98: @*/
     99: PetscErrorCode MFNViewFromOptions(MFN mfn,PetscObject obj,const char name[])
    100: {
    101:   PetscFunctionBegin;
    103:   PetscCall(PetscObjectViewFromOptions((PetscObject)mfn,obj,name));
    104:   PetscFunctionReturn(PETSC_SUCCESS);
    105: }
    106: /*@
    107:    MFNConvergedReasonView - Displays the reason an `MFN` solve converged or diverged.

    109:    Collective

    111:    Input Parameters:
    112: +  mfn - the matrix function solver context
    113: -  viewer - the viewer to display the reason

    115:    Options Database Key:
    116: .  -mfn_converged_reason - print reason for convergence/divergence, and number of iterations

    118:    Notes:
    119:    Use `MFNConvergedReasonViewFromOptions()` to display the reason based on values
    120:    in the options database.

    122:    To change the format of the output call `PetscViewerPushFormat()` before this
    123:    call. Use `PETSC_VIEWER_DEFAULT` for the default, or `PETSC_VIEWER_FAILED` to only
    124:    display a reason if it fails. The latter can be set in the command line with
    125:    `-mfn_converged_reason ::failed`.

    127:    Level: intermediate

    129: .seealso: [](ch:mfn), `MFNSetTolerances()`, `MFNGetIterationNumber()`, `MFNConvergedReasonViewFromOptions()`
    130: @*/
    131: PetscErrorCode MFNConvergedReasonView(MFN mfn,PetscViewer viewer)
    132: {
    133:   PetscBool         isAscii;
    134:   PetscViewerFormat format;

    136:   PetscFunctionBegin;
    137:   if (!viewer) viewer = PETSC_VIEWER_STDOUT_(PetscObjectComm((PetscObject)mfn));
    138:   PetscCall(PetscObjectTypeCompare((PetscObject)viewer,PETSCVIEWERASCII,&isAscii));
    139:   if (isAscii) {
    140:     PetscCall(PetscViewerGetFormat(viewer,&format));
    141:     PetscCall(PetscViewerASCIIAddTab(viewer,((PetscObject)mfn)->tablevel));
    142:     if (mfn->reason > 0 && format != PETSC_VIEWER_FAILED) PetscCall(PetscViewerASCIIPrintf(viewer,"%s Matrix function solve converged due to %s; iterations %" PetscInt_FMT "\n",((PetscObject)mfn)->prefix?((PetscObject)mfn)->prefix:"",MFNConvergedReasons[mfn->reason],mfn->its));
    143:     else if (mfn->reason <= 0) PetscCall(PetscViewerASCIIPrintf(viewer,"%s Matrix function solve did not converge due to %s; iterations %" PetscInt_FMT "\n",((PetscObject)mfn)->prefix?((PetscObject)mfn)->prefix:"",MFNConvergedReasons[mfn->reason],mfn->its));
    144:     PetscCall(PetscViewerASCIISubtractTab(viewer,((PetscObject)mfn)->tablevel));
    145:   }
    146:   PetscFunctionReturn(PETSC_SUCCESS);
    147: }

    149: /*@
    150:    MFNConvergedReasonViewFromOptions - Processes command line options to determine if/how
    151:    the `MFN` converged reason is to be viewed.

    153:    Collective

    155:    Input Parameter:
    156: .  mfn - the matrix function solver context

    158:    Level: intermediate

    160: .seealso: [](ch:mfn), `MFNConvergedReasonView()`
    161: @*/
    162: PetscErrorCode MFNConvergedReasonViewFromOptions(MFN mfn)
    163: {
    164:   PetscViewer       viewer;
    165:   PetscBool         flg;
    166:   static PetscBool  incall = PETSC_FALSE;
    167:   PetscViewerFormat format;

    169:   PetscFunctionBegin;
    170:   if (incall) PetscFunctionReturn(PETSC_SUCCESS);
    171:   incall = PETSC_TRUE;
    172:   PetscCall(PetscOptionsCreateViewer(PetscObjectComm((PetscObject)mfn),((PetscObject)mfn)->options,((PetscObject)mfn)->prefix,"-mfn_converged_reason",&viewer,&format,&flg));
    173:   if (flg) {
    174:     PetscCall(PetscViewerPushFormat(viewer,format));
    175:     PetscCall(MFNConvergedReasonView(mfn,viewer));
    176:     PetscCall(PetscViewerPopFormat(viewer));
    177:     PetscCall(PetscViewerDestroy(&viewer));
    178:   }
    179:   incall = PETSC_FALSE;
    180:   PetscFunctionReturn(PETSC_SUCCESS);
    181: }

    183: /*@
    184:    MFNCreate - Creates the `MFN` context.

    186:    Collective

    188:    Input Parameter:
    189: .  comm - MPI communicator

    191:    Output Parameter:
    192: .  outmfn - location to put the `MFN` context

    194:    Note:
    195:    The default `MFN` type is `MFNKRYLOV`.

    197:    Level: beginner

    199: .seealso: [](ch:mfn), `MFNSetUp()`, `MFNSolve()`, `MFNDestroy()`, `MFN`
    200: @*/
    201: PetscErrorCode MFNCreate(MPI_Comm comm,MFN *outmfn)
    202: {
    203:   MFN            mfn;

    205:   PetscFunctionBegin;
    206:   PetscAssertPointer(outmfn,2);
    207:   PetscCall(MFNInitializePackage());
    208:   PetscCall(SlepcHeaderCreate(mfn,MFN_CLASSID,"MFN","Matrix Function","MFN",comm,MFNDestroy,MFNView));

    210:   mfn->A               = NULL;
    211:   mfn->fn              = NULL;
    212:   mfn->max_it          = PETSC_DETERMINE;
    213:   mfn->ncv             = PETSC_DETERMINE;
    214:   mfn->tol             = PETSC_DETERMINE;
    215:   mfn->errorifnotconverged = PETSC_FALSE;

    217:   mfn->numbermonitors  = 0;

    219:   mfn->V               = NULL;
    220:   mfn->nwork           = 0;
    221:   mfn->work            = NULL;
    222:   mfn->data            = NULL;

    224:   mfn->its             = 0;
    225:   mfn->nv              = 0;
    226:   mfn->errest          = 0;
    227:   mfn->setupcalled     = 0;
    228:   mfn->reason          = MFN_CONVERGED_ITERATING;

    230:   *outmfn = mfn;
    231:   PetscFunctionReturn(PETSC_SUCCESS);
    232: }

    234: /*@
    235:    MFNSetType - Selects the particular solver to be used in the `MFN` object.

    237:    Logically Collective

    239:    Input Parameters:
    240: +  mfn  - the matrix function solver context
    241: -  type - a known method

    243:    Options Database Key:
    244: .  -mfn_type type - sets the method; use `-help` for a list of available methods

    246:    Notes:
    247:    See `MFNType` for available methods. The default is `MFNKRYLOV`.

    249:    Normally, it is best to use the `MFNSetFromOptions()` command and
    250:    then set the `MFN` type from the options database rather than by using
    251:    this routine.  Using the options database provides the user with
    252:    maximum flexibility in evaluating the different available methods.
    253:    The `MFNSetType()` routine is provided for those situations where it
    254:    is necessary to set the iterative solver independently of the command
    255:    line or options database.

    257:    Level: intermediate

    259: .seealso: [](ch:mfn), `MFNType`
    260: @*/
    261: PetscErrorCode MFNSetType(MFN mfn,MFNType type)
    262: {
    263:   PetscErrorCode (*r)(MFN);
    264:   PetscBool      match;

    266:   PetscFunctionBegin;
    268:   PetscAssertPointer(type,2);

    270:   PetscCall(PetscObjectTypeCompare((PetscObject)mfn,type,&match));
    271:   if (match) PetscFunctionReturn(PETSC_SUCCESS);

    273:   PetscCall(PetscFunctionListFind(MFNList,type,&r));
    274:   PetscCheck(r,PetscObjectComm((PetscObject)mfn),PETSC_ERR_ARG_UNKNOWN_TYPE,"Unknown MFN type given: %s",type);

    276:   PetscTryTypeMethod(mfn,destroy);
    277:   PetscCall(PetscMemzero(mfn->ops,sizeof(struct _MFNOps)));

    279:   mfn->setupcalled = 0;
    280:   PetscCall(PetscObjectChangeTypeName((PetscObject)mfn,type));
    281:   PetscCall((*r)(mfn));
    282:   PetscFunctionReturn(PETSC_SUCCESS);
    283: }

    285: /*@
    286:    MFNGetType - Gets the `MFN` type as a string from the `MFN` object.

    288:    Not Collective

    290:    Input Parameter:
    291: .  mfn - the matrix function solver context

    293:    Output Parameter:
    294: .  type - name of `MFN` method

    296:    Level: intermediate

    298: .seealso: [](ch:mfn), `MFNSetType()`
    299: @*/
    300: PetscErrorCode MFNGetType(MFN mfn,MFNType *type)
    301: {
    302:   PetscFunctionBegin;
    304:   PetscAssertPointer(type,2);
    305:   *type = ((PetscObject)mfn)->type_name;
    306:   PetscFunctionReturn(PETSC_SUCCESS);
    307: }

    309: /*@C
    310:    MFNRegister - Adds a method to the matrix function solver package.

    312:    Not Collective

    314:    Input Parameters:
    315: +  name - name of a new user-defined solver
    316: -  function - routine to create the solver context

    318:    Note:
    319:    `MFNRegister()` may be called multiple times to add several user-defined solvers.

    321:    Example Usage:
    322: .vb
    323:    MFNRegister("my_solver",MySolverCreate);
    324: .ve

    326:    Then, your solver can be chosen with the procedural interface via
    327: .vb
    328:    MFNSetType(mfn,"my_solver")
    329: .ve
    330:    or at runtime via the option `-mfn_type my_solver`.

    332:    Level: advanced

    334: .seealso: [](ch:mfn), `MFNRegisterAll()`
    335: @*/
    336: PetscErrorCode MFNRegister(const char *name,PetscErrorCode (*function)(MFN))
    337: {
    338:   PetscFunctionBegin;
    339:   PetscCall(MFNInitializePackage());
    340:   PetscCall(PetscFunctionListAdd(&MFNList,name,function));
    341:   PetscFunctionReturn(PETSC_SUCCESS);
    342: }

    344: /*@C
    345:    MFNMonitorRegister - Registers an `MFN` monitor routine that may be accessed with
    346:    `MFNMonitorSetFromOptions()`.

    348:    Not Collective

    350:    Input Parameters:
    351: +  name    - name of a new monitor routine
    352: .  vtype   - a `PetscViewerType` for the output
    353: .  format  - a `PetscViewerFormat` for the output
    354: .  monitor - monitor routine, see `MFNMonitorRegisterFn`
    355: .  create  - creation routine, or `NULL`
    356: -  destroy - destruction routine, or `NULL`

    358:    Notes:
    359:    `MFNMonitorRegister()` may be called multiple times to add several user-defined monitors.

    361:    The calling sequence for the given function matches the calling sequence of `MFNMonitorFn`
    362:    functions passed to `MFNMonitorSet()` with the additional requirement that its final argument
    363:    be a `PetscViewerAndFormat`.

    365:    Example Usage:
    366: .vb
    367:    MFNMonitorRegister("my_monitor",PETSCVIEWERASCII,PETSC_VIEWER_ASCII_INFO_DETAIL,MyMonitor,NULL,NULL);
    368: .ve

    370:    Then, your monitor can be chosen with the procedural interface via
    371: .vb
    372:    MFNMonitorSetFromOptions(mfn,"-mfn_monitor_my_monitor","my_monitor",NULL);
    373: .ve
    374:    or at runtime via the option `-mfn_monitor_my_monitor`.

    376:    Level: advanced

    378: .seealso: [](ch:mfn), `MFNMonitorSet()`, `MFNMonitorRegisterAll()`, `MFNMonitorSetFromOptions()`
    379: @*/
    380: PetscErrorCode MFNMonitorRegister(const char name[],PetscViewerType vtype,PetscViewerFormat format,MFNMonitorRegisterFn *monitor,MFNMonitorRegisterCreateFn *create,MFNMonitorRegisterDestroyFn *destroy)
    381: {
    382:   char           key[PETSC_MAX_PATH_LEN];

    384:   PetscFunctionBegin;
    385:   PetscCall(MFNInitializePackage());
    386:   PetscCall(SlepcMonitorMakeKey_Internal(name,vtype,format,key));
    387:   PetscCall(PetscFunctionListAdd(&MFNMonitorList,key,monitor));
    388:   if (create)  PetscCall(PetscFunctionListAdd(&MFNMonitorCreateList,key,create));
    389:   if (destroy) PetscCall(PetscFunctionListAdd(&MFNMonitorDestroyList,key,destroy));
    390:   PetscFunctionReturn(PETSC_SUCCESS);
    391: }

    393: /*@
    394:    MFNReset - Resets the `MFN` context to the initial state (prior to setup)
    395:    and destroys any allocated `Vec`s and `Mat`s.

    397:    Collective

    399:    Input Parameter:
    400: .  mfn - the matrix function solver context

    402:    Level: advanced

    404: .seealso: [](ch:mfn), `MFNDestroy()`
    405: @*/
    406: PetscErrorCode MFNReset(MFN mfn)
    407: {
    408:   PetscFunctionBegin;
    410:   if (!mfn) PetscFunctionReturn(PETSC_SUCCESS);
    411:   PetscTryTypeMethod(mfn,reset);
    412:   PetscCall(MatDestroy(&mfn->A));
    413:   PetscCall(BVDestroy(&mfn->V));
    414:   PetscCall(VecDestroyVecs(mfn->nwork,&mfn->work));
    415:   mfn->nwork = 0;
    416:   mfn->setupcalled = 0;
    417:   PetscFunctionReturn(PETSC_SUCCESS);
    418: }

    420: /*@
    421:    MFNDestroy - Destroys the `MFN` context.

    423:    Collective

    425:    Input Parameter:
    426: .  mfn - the matrix function solver context

    428:    Level: beginner

    430: .seealso: [](ch:mfn), `MFNCreate()`, `MFNSetUp()`, `MFNSolve()`
    431: @*/
    432: PetscErrorCode MFNDestroy(MFN *mfn)
    433: {
    434:   PetscFunctionBegin;
    435:   if (!*mfn) PetscFunctionReturn(PETSC_SUCCESS);
    437:   if (--((PetscObject)*mfn)->refct > 0) { *mfn = NULL; PetscFunctionReturn(PETSC_SUCCESS); }
    438:   PetscCall(MFNReset(*mfn));
    439:   PetscTryTypeMethod(*mfn,destroy);
    440:   PetscCall(FNDestroy(&(*mfn)->fn));
    441:   PetscCall(MatDestroy(&(*mfn)->AT));
    442:   PetscCall(MFNMonitorCancel(*mfn));
    443:   PetscCall(PetscHeaderDestroy(mfn));
    444:   PetscFunctionReturn(PETSC_SUCCESS);
    445: }

    447: /*@
    448:    MFNSetBV - Associates a basis vectors object to the matrix function solver.

    450:    Collective

    452:    Input Parameters:
    453: +  mfn - the matrix function solver context
    454: -  bv  - the basis vectors object

    456:    Note:
    457:    Use `MFNGetBV()` to retrieve the basis vectors context (for example,
    458:    to free it at the end of the computations).

    460:    Level: advanced

    462: .seealso: [](ch:mfn), `MFNGetBV()`
    463: @*/
    464: PetscErrorCode MFNSetBV(MFN mfn,BV bv)
    465: {
    466:   PetscFunctionBegin;
    469:   PetscCheckSameComm(mfn,1,bv,2);
    470:   PetscCall(PetscObjectReference((PetscObject)bv));
    471:   PetscCall(BVDestroy(&mfn->V));
    472:   mfn->V = bv;
    473:   PetscFunctionReturn(PETSC_SUCCESS);
    474: }

    476: /*@
    477:    MFNGetBV - Obtain the basis vectors object associated to the matrix
    478:    function solver.

    480:    Not Collective

    482:    Input Parameter:
    483: .  mfn - the matrix function solver context

    485:    Output Parameter:
    486: .  bv - basis vectors context

    488:    Level: advanced

    490: .seealso: [](ch:mfn), `MFNSetBV()`
    491: @*/
    492: PetscErrorCode MFNGetBV(MFN mfn,BV *bv)
    493: {
    494:   PetscFunctionBegin;
    496:   PetscAssertPointer(bv,2);
    497:   if (!mfn->V) {
    498:     PetscCall(BVCreate(PetscObjectComm((PetscObject)mfn),&mfn->V));
    499:     PetscCall(PetscObjectIncrementTabLevel((PetscObject)mfn->V,(PetscObject)mfn,0));
    500:     PetscCall(PetscObjectSetOptions((PetscObject)mfn->V,((PetscObject)mfn)->options));
    501:   }
    502:   *bv = mfn->V;
    503:   PetscFunctionReturn(PETSC_SUCCESS);
    504: }

    506: /*@
    507:    MFNSetFN - Specifies the function to be computed.

    509:    Collective

    511:    Input Parameters:
    512: +  mfn - the matrix function solver context
    513: -  fn  - the math function object

    515:    Notes:
    516:    At a later time, use `MFNGetFN()` to retrieve the math function context
    517:    (for example, to free it at the end of the computations).

    519:    This function is not called in normal usage. Instead, it is easier to
    520:    extract the internal `FN` object with `MFNGetFN()` and modify it.

    522:    Level: beginner

    524: .seealso: [](ch:mfn), `MFNGetFN()`
    525: @*/
    526: PetscErrorCode MFNSetFN(MFN mfn,FN fn)
    527: {
    528:   PetscFunctionBegin;
    531:   PetscCheckSameComm(mfn,1,fn,2);
    532:   PetscCall(PetscObjectReference((PetscObject)fn));
    533:   PetscCall(FNDestroy(&mfn->fn));
    534:   mfn->fn = fn;
    535:   PetscFunctionReturn(PETSC_SUCCESS);
    536: }

    538: /*@
    539:    MFNGetFN - Obtain the math function object associated to the `MFN` object.

    541:    Not Collective

    543:    Input Parameter:
    544: .  mfn - the matrix function solver context

    546:    Output Parameter:
    547: .  fn - math function context

    549:    Note:
    550:    This is the usual way to specify the function that needs to be applied
    551:    to a given vector in `MFNSolve()`.

    553:    Level: beginner

    555: .seealso: [](ch:mfn), `MFNSetFN()`, `MFNSolve()`
    556: @*/
    557: PetscErrorCode MFNGetFN(MFN mfn,FN *fn)
    558: {
    559:   PetscFunctionBegin;
    561:   PetscAssertPointer(fn,2);
    562:   if (!mfn->fn) {
    563:     PetscCall(FNCreate(PetscObjectComm((PetscObject)mfn),&mfn->fn));
    564:     PetscCall(PetscObjectIncrementTabLevel((PetscObject)mfn->fn,(PetscObject)mfn,0));
    565:     PetscCall(PetscObjectSetOptions((PetscObject)mfn->fn,((PetscObject)mfn)->options));
    566:   }
    567:   *fn = mfn->fn;
    568:   PetscFunctionReturn(PETSC_SUCCESS);
    569: }