Actual source code: lmeopts.c
slepc-3.21.1 2024-04-26
Report Typos and Errors

      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 options that can be set via the command-line
     12:    or procedurally
     13: */

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

     18: /*@C
     19:    LMEMonitorSetFromOptions - Sets a monitor function and viewer appropriate for the type
     20:    indicated by the user.

     22:    Collective

     24:    Input Parameters:
     25: +  lme      - the linear matrix equation context
     26: .  opt  - the command line option for this monitor
     27: .  name - the monitor type one is seeking
     28: -  ctx  - an optional user context for the monitor, or NULL

     30:    Level: developer

     32: .seealso: LMEMonitorSet()
     33: @*/
     34: PetscErrorCode LMEMonitorSetFromOptions(LME lme,const char opt[],const char name[],void *ctx)
     35: {
     36:   PetscErrorCode       (*mfunc)(LME,PetscInt,PetscReal,void*);
     37:   PetscErrorCode       (*cfunc)(PetscViewer,PetscViewerFormat,void*,PetscViewerAndFormat**);
     38:   PetscErrorCode       (*dfunc)(PetscViewerAndFormat**);
     39:   PetscViewerAndFormat *vf;
     40:   PetscViewer          viewer;
     41:   PetscViewerFormat    format;
     42:   PetscViewerType      vtype;
     43:   char                 key[PETSC_MAX_PATH_LEN];
     44:   PetscBool            flg;

     46:   PetscFunctionBegin;
     47:   PetscCall(PetscOptionsGetViewer(PetscObjectComm((PetscObject)lme),((PetscObject)lme)->options,((PetscObject)lme)->prefix,opt,&viewer,&format,&flg));
     48:   if (!flg) PetscFunctionReturn(PETSC_SUCCESS);

     50:   PetscCall(PetscViewerGetType(viewer,&vtype));
     51:   PetscCall(SlepcMonitorMakeKey_Internal(name,vtype,format,key));
     52:   PetscCall(PetscFunctionListFind(LMEMonitorList,key,&mfunc));
     53:   PetscCheck(mfunc,PetscObjectComm((PetscObject)lme),PETSC_ERR_SUP,"Specified viewer and format not supported");
     54:   PetscCall(PetscFunctionListFind(LMEMonitorCreateList,key,&cfunc));
     55:   PetscCall(PetscFunctionListFind(LMEMonitorDestroyList,key,&dfunc));
     56:   if (!cfunc) cfunc = PetscViewerAndFormatCreate_Internal;
     57:   if (!dfunc) dfunc = PetscViewerAndFormatDestroy;

     59:   PetscCall((*cfunc)(viewer,format,ctx,&vf));
     60:   PetscCall(PetscOptionsRestoreViewer(&viewer));
     61:   PetscCall(LMEMonitorSet(lme,mfunc,vf,(PetscErrorCode(*)(void **))dfunc));
     62:   PetscFunctionReturn(PETSC_SUCCESS);
     63: }

     65: /*@
     66:    LMESetFromOptions - Sets LME options from the options database.
     67:    This routine must be called before LMESetUp() if the user is to be
     68:    allowed to set the solver type.

     70:    Collective

     72:    Input Parameters:
     73: .  lme - the linear matrix equation solver context

     75:    Notes:
     76:    To see all options, run your program with the -help option.

     78:    Level: beginner

     80: .seealso: LMESetOptionsPrefix()
     81: @*/
     82: PetscErrorCode LMESetFromOptions(LME lme)
     83: {
     84:   char           type[256];
     85:   PetscBool      set,flg,flg1,flg2;
     86:   PetscReal      r;
     87:   PetscInt       i;

     89:   PetscFunctionBegin;
     91:   PetscCall(LMERegisterAll());
     92:   PetscObjectOptionsBegin((PetscObject)lme);
     93:     PetscCall(PetscOptionsFList("-lme_type","Linear matrix equation","LMESetType",LMEList,(char*)(((PetscObject)lme)->type_name?((PetscObject)lme)->type_name:LMEKRYLOV),type,sizeof(type),&flg));
     94:     if (flg) PetscCall(LMESetType(lme,type));
     95:     else if (!((PetscObject)lme)->type_name) PetscCall(LMESetType(lme,LMEKRYLOV));

     97:     PetscCall(PetscOptionsBoolGroupBegin("-lme_lyapunov","Continuous-time Lyapunov equation","LMESetProblemType",&flg));
     98:     if (flg) PetscCall(LMESetProblemType(lme,LME_LYAPUNOV));
     99:     PetscCall(PetscOptionsBoolGroup("-lme_sylvester","Continuous-time Sylvester equation","LMESetProblemType",&flg));
    100:     if (flg) PetscCall(LMESetProblemType(lme,LME_SYLVESTER));
    101:     PetscCall(PetscOptionsBoolGroup("-lme_gen_lyapunov","Generalized Lyapunov equation","LMESetProblemType",&flg));
    102:     if (flg) PetscCall(LMESetProblemType(lme,LME_GEN_LYAPUNOV));
    103:     PetscCall(PetscOptionsBoolGroup("-lme_gen_sylvester","Generalized Sylvester equation","LMESetProblemType",&flg));
    104:     if (flg) PetscCall(LMESetProblemType(lme,LME_GEN_SYLVESTER));
    105:     PetscCall(PetscOptionsBoolGroup("-lme_dt_lyapunov","Discrete-time Lyapunov equation","LMESetProblemType",&flg));
    106:     if (flg) PetscCall(LMESetProblemType(lme,LME_DT_LYAPUNOV));
    107:     PetscCall(PetscOptionsBoolGroupEnd("-lme_stein","Stein equation","LMESetProblemType",&flg));
    108:     if (flg) PetscCall(LMESetProblemType(lme,LME_STEIN));

    110:     i = lme->max_it;
    111:     PetscCall(PetscOptionsInt("-lme_max_it","Maximum number of iterations","LMESetTolerances",lme->max_it,&i,&flg1));
    112:     if (!flg1) i = PETSC_DEFAULT;
    113:     r = lme->tol;
    114:     PetscCall(PetscOptionsReal("-lme_tol","Tolerance","LMESetTolerances",SlepcDefaultTol(lme->tol),&r,&flg2));
    115:     if (flg1 || flg2) PetscCall(LMESetTolerances(lme,r,i));

    117:     PetscCall(PetscOptionsInt("-lme_ncv","Number of basis vectors","LMESetDimensions",lme->ncv,&i,&flg));
    118:     if (flg) PetscCall(LMESetDimensions(lme,i));

    120:     PetscCall(PetscOptionsBool("-lme_error_if_not_converged","Generate error if solver does not converge","LMESetErrorIfNotConverged",lme->errorifnotconverged,&lme->errorifnotconverged,NULL));

    122:     /* -----------------------------------------------------------------------*/
    123:     /*
    124:       Cancels all monitors hardwired into code before call to LMESetFromOptions()
    125:     */
    126:     PetscCall(PetscOptionsBool("-lme_monitor_cancel","Remove any hardwired monitor routines","LMEMonitorCancel",PETSC_FALSE,&flg,&set));
    127:     if (set && flg) PetscCall(LMEMonitorCancel(lme));
    128:     PetscCall(LMEMonitorSetFromOptions(lme,"-lme_monitor","error_estimate",NULL));

    130:     /* -----------------------------------------------------------------------*/
    131:     PetscCall(PetscOptionsName("-lme_view","Print detailed information on solver used","LMEView",&set));

    133:     PetscTryTypeMethod(lme,setfromoptions,PetscOptionsObject);
    134:     PetscCall(PetscObjectProcessOptionsHandlers((PetscObject)lme,PetscOptionsObject));
    135:   PetscOptionsEnd();

    137:   if (!lme->V) PetscCall(LMEGetBV(lme,&lme->V));
    138:   PetscCall(BVSetFromOptions(lme->V));
    139:   PetscFunctionReturn(PETSC_SUCCESS);
    140: }

    142: /*@
    143:    LMESetProblemType - Specifies the type of matrix equation to be solved.

    145:    Logically Collective

    147:    Input Parameters:
    148: +  lme  - the linear matrix equation solver context
    149: -  type - a known type of matrix equation

    151:    Options Database Keys:
    152: +  -lme_lyapunov - continuous-time Lyapunov equation A*X+X*A'=-C
    153: .  -lme_sylvester - continuous-time Sylvester equation A*X+X*B=C
    154: .  -lme_gen_lyapunov - generalized Lyapunov equation A*X*D'+D*X*A'=-C
    155: .  -lme_gen_sylvester - generalized Sylvester equation A*X*E+D*X*B=C
    156: .  -lme_dt_lyapunov - discrete-time Lyapunov equation A*X*A'-X=-C
    157: -  -lme_stein - Stein equation A*X*E+X=C

    159:    Notes:
    160:    The coefficient matrices A, B, D, E must be provided via LMESetCoefficients(),
    161:    but some of them are optional depending on the matrix equation.

    163: .vb
    164:                             equation              A    B    D    E
    165:                           -----------------      ---  ---  ---  ---
    166:        LME_LYAPUNOV        A*X+X*A'=-C           yes (A-t)  -    -
    167:        LME_SYLVESTER       A*X+X*B=C             yes  yes   -    -
    168:        LME_GEN_LYAPUNOV    A*X*D'+D*X*A'=-C      yes (A-t) yes (D-t)
    169:        LME_GEN_SYLVESTER   A*X*E+D*X*B=C         yes  yes  yes  yes
    170:        LME_DT_LYAPUNOV     A*X*A'-X=-C           yes   -    -  (A-t)
    171:        LME_STEIN           A*X*E+X=C             yes   -    -   yes
    172: .ve

    174:    In the above table, the notation (A-t) means that this matrix need
    175:    not be passed, but the user may choose to pass an explicit transpose
    176:    of matrix A (for improved efficiency).

    178:    Also note that some of the equation types impose restrictions on the
    179:    properties of the coefficient matrices and possibly on the right-hand
    180:    side C.

    182:    Level: beginner

    184: .seealso: LMESetCoefficients(), LMESetType(), LMEGetProblemType(), LMEProblemType
    185: @*/
    186: PetscErrorCode LMESetProblemType(LME lme,LMEProblemType type)
    187: {
    188:   PetscFunctionBegin;
    191:   if (type == lme->problem_type) PetscFunctionReturn(PETSC_SUCCESS);
    192:   switch (type) {
    193:     case LME_LYAPUNOV:
    194:     case LME_SYLVESTER:
    195:     case LME_GEN_LYAPUNOV:
    196:     case LME_GEN_SYLVESTER:
    197:     case LME_DT_LYAPUNOV:
    198:     case LME_STEIN:
    199:       break;
    200:     default:
    201:       SETERRQ(PetscObjectComm((PetscObject)lme),PETSC_ERR_ARG_WRONG,"Unknown matrix equation type");
    202:   }
    203:   lme->problem_type = type;
    204:   lme->setupcalled  = PETSC_FALSE;
    205:   PetscFunctionReturn(PETSC_SUCCESS);
    206: }

    208: /*@
    209:    LMEGetProblemType - Gets the matrix equation type from the LME object.

    211:    Not Collective

    213:    Input Parameter:
    214: .  lme - the linear matrix equation solver context

    216:    Output Parameter:
    217: .  type - name of LME problem type

    219:    Level: intermediate

    221: .seealso: LMESetProblemType(), LMEProblemType
    222: @*/
    223: PetscErrorCode LMEGetProblemType(LME lme,LMEProblemType *type)
    224: {
    225:   PetscFunctionBegin;
    227:   PetscAssertPointer(type,2);
    228:   *type = lme->problem_type;
    229:   PetscFunctionReturn(PETSC_SUCCESS);
    230: }

    232: /*@C
    233:    LMEGetTolerances - Gets the tolerance and maximum iteration count used
    234:    by the LME convergence tests.

    236:    Not Collective

    238:    Input Parameter:
    239: .  lme - the linear matrix equation solver context

    241:    Output Parameters:
    242: +  tol - the convergence tolerance
    243: -  maxits - maximum number of iterations

    245:    Notes:
    246:    The user can specify NULL for any parameter that is not needed.

    248:    Level: intermediate

    250: .seealso: LMESetTolerances()
    251: @*/
    252: PetscErrorCode LMEGetTolerances(LME lme,PetscReal *tol,PetscInt *maxits)
    253: {
    254:   PetscFunctionBegin;
    256:   if (tol)    *tol    = lme->tol;
    257:   if (maxits) *maxits = lme->max_it;
    258:   PetscFunctionReturn(PETSC_SUCCESS);
    259: }

    261: /*@
    262:    LMESetTolerances - Sets the tolerance and maximum iteration count used
    263:    by the LME convergence tests.

    265:    Logically Collective

    267:    Input Parameters:
    268: +  lme - the linear matrix equation solver context
    269: .  tol - the convergence tolerance
    270: -  maxits - maximum number of iterations to use

    272:    Options Database Keys:
    273: +  -lme_tol <tol> - Sets the convergence tolerance
    274: -  -lme_max_it <maxits> - Sets the maximum number of iterations allowed

    276:    Notes:
    277:    Use PETSC_DEFAULT for either argument to assign a reasonably good value.

    279:    Level: intermediate

    281: .seealso: LMEGetTolerances()
    282: @*/
    283: PetscErrorCode LMESetTolerances(LME lme,PetscReal tol,PetscInt maxits)
    284: {
    285:   PetscFunctionBegin;
    289:   if (tol == (PetscReal)PETSC_DEFAULT) {
    290:     lme->tol = PETSC_DEFAULT;
    291:     lme->setupcalled = 0;
    292:   } else {
    293:     PetscCheck(tol>0.0,PetscObjectComm((PetscObject)lme),PETSC_ERR_ARG_OUTOFRANGE,"Illegal value of tol. Must be > 0");
    294:     lme->tol = tol;
    295:   }
    296:   if (maxits == PETSC_DEFAULT || maxits == PETSC_DECIDE) {
    297:     lme->max_it = PETSC_DEFAULT;
    298:     lme->setupcalled = 0;
    299:   } else {
    300:     PetscCheck(maxits>0,PetscObjectComm((PetscObject)lme),PETSC_ERR_ARG_OUTOFRANGE,"Illegal value of maxits. Must be > 0");
    301:     lme->max_it = maxits;
    302:   }
    303:   PetscFunctionReturn(PETSC_SUCCESS);
    304: }

    306: /*@
    307:    LMEGetDimensions - Gets the dimension of the subspace used by the solver.

    309:    Not Collective

    311:    Input Parameter:
    312: .  lme - the linear matrix equation solver context

    314:    Output Parameter:
    315: .  ncv - the maximum dimension of the subspace to be used by the solver

    317:    Level: intermediate

    319: .seealso: LMESetDimensions()
    320: @*/
    321: PetscErrorCode LMEGetDimensions(LME lme,PetscInt *ncv)
    322: {
    323:   PetscFunctionBegin;
    325:   PetscAssertPointer(ncv,2);
    326:   *ncv = lme->ncv;
    327:   PetscFunctionReturn(PETSC_SUCCESS);
    328: }

    330: /*@
    331:    LMESetDimensions - Sets the dimension of the subspace to be used by the solver.

    333:    Logically Collective

    335:    Input Parameters:
    336: +  lme - the linear matrix equation solver context
    337: -  ncv - the maximum dimension of the subspace to be used by the solver

    339:    Options Database Keys:
    340: .  -lme_ncv <ncv> - Sets the dimension of the subspace

    342:    Notes:
    343:    Use PETSC_DEFAULT for ncv to assign a reasonably good value, which is
    344:    dependent on the solution method.

    346:    Level: intermediate

    348: .seealso: LMEGetDimensions()
    349: @*/
    350: PetscErrorCode LMESetDimensions(LME lme,PetscInt ncv)
    351: {
    352:   PetscFunctionBegin;
    355:   if (ncv == PETSC_DECIDE || ncv == PETSC_DEFAULT) {
    356:     lme->ncv = PETSC_DEFAULT;
    357:   } else {
    358:     PetscCheck(ncv>0,PetscObjectComm((PetscObject)lme),PETSC_ERR_ARG_OUTOFRANGE,"Illegal value of ncv. Must be > 0");
    359:     lme->ncv = ncv;
    360:   }
    361:   lme->setupcalled = 0;
    362:   PetscFunctionReturn(PETSC_SUCCESS);
    363: }

    365: /*@
    366:    LMESetErrorIfNotConverged - Causes LMESolve() to generate an error if the
    367:    solver has not converged.

    369:    Logically Collective

    371:    Input Parameters:
    372: +  lme - the linear matrix equation solver context
    373: -  flg - PETSC_TRUE indicates you want the error generated

    375:    Options Database Keys:
    376: .  -lme_error_if_not_converged - this takes an optional truth value (0/1/no/yes/true/false)

    378:    Level: intermediate

    380:    Note:
    381:    Normally SLEPc continues if the solver fails to converge, you can call
    382:    LMEGetConvergedReason() after a LMESolve() to determine if it has converged.

    384: .seealso: LMEGetErrorIfNotConverged()
    385: @*/
    386: PetscErrorCode LMESetErrorIfNotConverged(LME lme,PetscBool flg)
    387: {
    388:   PetscFunctionBegin;
    391:   lme->errorifnotconverged = flg;
    392:   PetscFunctionReturn(PETSC_SUCCESS);
    393: }

    395: /*@
    396:    LMEGetErrorIfNotConverged - Return a flag indicating whether LMESolve() will
    397:    generate an error if the solver does not converge.

    399:    Not Collective

    401:    Input Parameter:
    402: .  lme - the linear matrix equation solver context

    404:    Output Parameter:
    405: .  flag - PETSC_TRUE if it will generate an error, else PETSC_FALSE

    407:    Level: intermediate

    409: .seealso: LMESetErrorIfNotConverged()
    410: @*/
    411: PetscErrorCode LMEGetErrorIfNotConverged(LME lme,PetscBool *flag)
    412: {
    413:   PetscFunctionBegin;
    415:   PetscAssertPointer(flag,2);
    416:   *flag = lme->errorifnotconverged;
    417:   PetscFunctionReturn(PETSC_SUCCESS);
    418: }

    420: /*@C
    421:    LMESetOptionsPrefix - Sets the prefix used for searching for all
    422:    LME options in the database.

    424:    Logically Collective

    426:    Input Parameters:
    427: +  lme - the linear matrix equation solver context
    428: -  prefix - the prefix string to prepend to all LME option requests

    430:    Notes:
    431:    A hyphen (-) must NOT be given at the beginning of the prefix name.
    432:    The first character of all runtime options is AUTOMATICALLY the
    433:    hyphen.

    435:    For example, to distinguish between the runtime options for two
    436:    different LME contexts, one could call
    437: .vb
    438:       LMESetOptionsPrefix(lme1,"fun1_")
    439:       LMESetOptionsPrefix(lme2,"fun2_")
    440: .ve

    442:    Level: advanced

    444: .seealso: LMEAppendOptionsPrefix(), LMEGetOptionsPrefix()
    445: @*/
    446: PetscErrorCode LMESetOptionsPrefix(LME lme,const char *prefix)
    447: {
    448:   PetscFunctionBegin;
    450:   if (!lme->V) PetscCall(LMEGetBV(lme,&lme->V));
    451:   PetscCall(BVSetOptionsPrefix(lme->V,prefix));
    452:   PetscCall(PetscObjectSetOptionsPrefix((PetscObject)lme,prefix));
    453:   PetscFunctionReturn(PETSC_SUCCESS);
    454: }

    456: /*@C
    457:    LMEAppendOptionsPrefix - Appends to the prefix used for searching for all
    458:    LME options in the database.

    460:    Logically Collective

    462:    Input Parameters:
    463: +  lme - the linear matrix equation solver context
    464: -  prefix - the prefix string to prepend to all LME option requests

    466:    Notes:
    467:    A hyphen (-) must NOT be given at the beginning of the prefix name.
    468:    The first character of all runtime options is AUTOMATICALLY the hyphen.

    470:    Level: advanced

    472: .seealso: LMESetOptionsPrefix(), LMEGetOptionsPrefix()
    473: @*/
    474: PetscErrorCode LMEAppendOptionsPrefix(LME lme,const char *prefix)
    475: {
    476:   PetscFunctionBegin;
    478:   if (!lme->V) PetscCall(LMEGetBV(lme,&lme->V));
    479:   PetscCall(BVAppendOptionsPrefix(lme->V,prefix));
    480:   PetscCall(PetscObjectAppendOptionsPrefix((PetscObject)lme,prefix));
    481:   PetscFunctionReturn(PETSC_SUCCESS);
    482: }

    484: /*@C
    485:    LMEGetOptionsPrefix - Gets the prefix used for searching for all
    486:    LME options in the database.

    488:    Not Collective

    490:    Input Parameters:
    491: .  lme - the linear matrix equation solver context

    493:    Output Parameters:
    494: .  prefix - pointer to the prefix string used is returned

    496:    Note:
    497:    On the Fortran side, the user should pass in a string 'prefix' of
    498:    sufficient length to hold the prefix.

    500:    Level: advanced

    502: .seealso: LMESetOptionsPrefix(), LMEAppendOptionsPrefix()
    503: @*/
    504: PetscErrorCode LMEGetOptionsPrefix(LME lme,const char *prefix[])
    505: {
    506:   PetscFunctionBegin;
    508:   PetscAssertPointer(prefix,2);
    509:   PetscCall(PetscObjectGetOptionsPrefix((PetscObject)lme,prefix));
    510:   PetscFunctionReturn(PETSC_SUCCESS);
    511: }