Actual source code: epsbasic.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 EPS routines
     12: */

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

     16: /* Logging support */
     17: PetscClassId      EPS_CLASSID = 0;
     18: PetscLogEvent     EPS_SetUp = 0,EPS_Solve = 0,EPS_CISS_SVD = 0;

     20: /* List of registered EPS routines */
     21: PetscFunctionList EPSList = NULL;
     22: PetscBool         EPSRegisterAllCalled = PETSC_FALSE;

     24: /* List of registered EPS monitors */
     25: PetscFunctionList EPSMonitorList              = NULL;
     26: PetscFunctionList EPSMonitorCreateList        = NULL;
     27: PetscFunctionList EPSMonitorDestroyList       = NULL;
     28: PetscBool         EPSMonitorRegisterAllCalled = PETSC_FALSE;

     30: /*@
     31:    EPSCreate - Creates the `EPS` context.

     33:    Collective

     35:    Input Parameter:
     36: .  comm - MPI communicator

     38:    Output Parameter:
     39: .  outeps - location to put the `EPS` context

     41:    Note:
     42:    The default `EPS` type is `EPSKRYLOVSCHUR`.

     44:    Level: beginner

     46: .seealso: [](ch:eps), `EPSSetUp()`, `EPSSolve()`, `EPSDestroy()`, `EPS`
     47: @*/
     48: PetscErrorCode EPSCreate(MPI_Comm comm,EPS *outeps)
     49: {
     50:   EPS            eps;

     52:   PetscFunctionBegin;
     53:   PetscAssertPointer(outeps,2);
     54:   PetscCall(EPSInitializePackage());
     55:   PetscCall(SlepcHeaderCreate(eps,EPS_CLASSID,"EPS","Eigenvalue Problem Solver","EPS",comm,EPSDestroy,EPSView));

     57:   eps->max_it          = PETSC_DETERMINE;
     58:   eps->nev             = 0;
     59:   eps->ncv             = PETSC_DETERMINE;
     60:   eps->mpd             = PETSC_DETERMINE;
     61:   eps->nini            = 0;
     62:   eps->nds             = 0;
     63:   eps->target          = 0.0;
     64:   eps->tol             = PETSC_DETERMINE;
     65:   eps->thres           = PETSC_MIN_REAL;
     66:   eps->threlative      = PETSC_FALSE;
     67:   eps->conv            = EPS_CONV_REL;
     68:   eps->stop            = EPS_STOP_BASIC;
     69:   eps->which           = (EPSWhich)0;
     70:   eps->inta            = 0.0;
     71:   eps->intb            = 0.0;
     72:   eps->problem_type    = (EPSProblemType)0;
     73:   eps->extraction      = EPS_RITZ;
     74:   eps->balance         = EPS_BALANCE_NONE;
     75:   eps->balance_its     = 5;
     76:   eps->balance_cutoff  = 1e-8;
     77:   eps->trueres         = PETSC_FALSE;
     78:   eps->trackall        = PETSC_FALSE;
     79:   eps->purify          = PETSC_TRUE;
     80:   eps->twosided        = PETSC_FALSE;

     82:   eps->converged       = EPSConvergedRelative;
     83:   eps->convergeduser   = NULL;
     84:   eps->convergeddestroy= NULL;
     85:   eps->stopping        = EPSStoppingBasic;
     86:   eps->stoppinguser    = NULL;
     87:   eps->stoppingdestroy = NULL;
     88:   eps->arbitrary       = NULL;
     89:   eps->arbitrarydestroy= NULL;
     90:   eps->convergedctx    = NULL;
     91:   eps->stoppingctx     = NULL;
     92:   eps->arbitraryctx    = NULL;
     93:   eps->numbermonitors  = 0;

     95:   eps->st              = NULL;
     96:   eps->ds              = NULL;
     97:   eps->V               = NULL;
     98:   eps->W               = NULL;
     99:   eps->rg              = NULL;
    100:   eps->D               = NULL;
    101:   eps->IS              = NULL;
    102:   eps->ISL             = NULL;
    103:   eps->defl            = NULL;
    104:   eps->eigr            = NULL;
    105:   eps->eigi            = NULL;
    106:   eps->errest          = NULL;
    107:   eps->rr              = NULL;
    108:   eps->ri              = NULL;
    109:   eps->perm            = NULL;
    110:   eps->nwork           = 0;
    111:   eps->work            = NULL;
    112:   eps->data            = NULL;

    114:   eps->state           = EPS_STATE_INITIAL;
    115:   eps->categ           = EPS_CATEGORY_KRYLOV;
    116:   eps->nconv           = 0;
    117:   eps->its             = 0;
    118:   eps->nloc            = 0;
    119:   eps->nrma            = 0.0;
    120:   eps->nrmb            = 0.0;
    121:   eps->useds           = PETSC_FALSE;
    122:   eps->isgeneralized   = PETSC_FALSE;
    123:   eps->ispositive      = PETSC_FALSE;
    124:   eps->ishermitian     = PETSC_FALSE;
    125:   eps->isstructured    = PETSC_FALSE;
    126:   eps->reason          = EPS_CONVERGED_ITERATING;

    128:   PetscCall(PetscNew(&eps->sc));
    129:   *outeps = eps;
    130:   PetscFunctionReturn(PETSC_SUCCESS);
    131: }

    133: /*@
    134:    EPSSetType - Selects the particular solver to be used in the `EPS` object.

    136:    Logically Collective

    138:    Input Parameters:
    139: +  eps  - the linear eigensolver context
    140: -  type - a known method

    142:    Options Database Key:
    143: .  -eps_type type - sets the method; use `-help` for a list of available methods

    145:    Notes:
    146:    See `EPSType` for available methods. The default is `EPSKRYLOVSCHUR`.

    148:    Normally, it is best to use the `EPSSetFromOptions()` command and
    149:    then set the `EPS` type from the options database rather than by using
    150:    this routine.  Using the options database provides the user with
    151:    maximum flexibility in evaluating the different available methods.
    152:    The `EPSSetType()` routine is provided for those situations where it
    153:    is necessary to set the iterative solver independently of the command
    154:    line or options database.

    156:    Level: intermediate

    158: .seealso: [](ch:eps), `STSetType()`, `EPSType`
    159: @*/
    160: PetscErrorCode EPSSetType(EPS eps,EPSType type)
    161: {
    162:   PetscErrorCode (*r)(EPS);
    163:   PetscBool      match;

    165:   PetscFunctionBegin;
    167:   PetscAssertPointer(type,2);

    169:   PetscCall(PetscObjectTypeCompare((PetscObject)eps,type,&match));
    170:   if (match) PetscFunctionReturn(PETSC_SUCCESS);

    172:   PetscCall(PetscFunctionListFind(EPSList,type,&r));
    173:   PetscCheck(r,PetscObjectComm((PetscObject)eps),PETSC_ERR_ARG_UNKNOWN_TYPE,"Unknown EPS type given: %s",type);

    175:   PetscTryTypeMethod(eps,destroy);
    176:   PetscCall(PetscMemzero(eps->ops,sizeof(struct _EPSOps)));

    178:   eps->state = EPS_STATE_INITIAL;
    179:   PetscCall(PetscObjectChangeTypeName((PetscObject)eps,type));
    180:   PetscCall((*r)(eps));
    181:   PetscFunctionReturn(PETSC_SUCCESS);
    182: }

    184: /*@
    185:    EPSGetType - Gets the `EPS` type as a string from the `EPS` object.

    187:    Not Collective

    189:    Input Parameter:
    190: .  eps - the linear eigensolver context

    192:    Output Parameter:
    193: .  type - name of `EPS` method

    195:    Level: intermediate

    197: .seealso: [](ch:eps), `EPSSetType()`
    198: @*/
    199: PetscErrorCode EPSGetType(EPS eps,EPSType *type)
    200: {
    201:   PetscFunctionBegin;
    203:   PetscAssertPointer(type,2);
    204:   *type = ((PetscObject)eps)->type_name;
    205:   PetscFunctionReturn(PETSC_SUCCESS);
    206: }

    208: /*@C
    209:    EPSRegister - Adds a method to the eigenproblem solver package.

    211:    Not Collective

    213:    Input Parameters:
    214: +  name - name of a new user-defined solver
    215: -  function - routine to create the solver context

    217:    Note:
    218:    `EPSRegister()` may be called multiple times to add several user-defined solvers.

    220:    Example Usage:
    221: .vb
    222:    EPSRegister("my_solver",MySolverCreate);
    223: .ve

    225:    Then, your solver can be chosen with the procedural interface via
    226: .vb
    227:    EPSSetType(eps,"my_solver")
    228: .ve
    229:    or at runtime via the option `-eps_type my_solver`.

    231:    Level: advanced

    233: .seealso: [](ch:eps), `EPSRegisterAll()`
    234: @*/
    235: PetscErrorCode EPSRegister(const char *name,PetscErrorCode (*function)(EPS))
    236: {
    237:   PetscFunctionBegin;
    238:   PetscCall(EPSInitializePackage());
    239:   PetscCall(PetscFunctionListAdd(&EPSList,name,function));
    240:   PetscFunctionReturn(PETSC_SUCCESS);
    241: }

    243: /*@C
    244:    EPSMonitorRegister - Registers an `EPS` monitor routine that may be accessed with
    245:    `EPSMonitorSetFromOptions()`.

    247:    Not Collective

    249:    Input Parameters:
    250: +  name    - name of a new monitor routine
    251: .  vtype   - a `PetscViewerType` for the output
    252: .  format  - a `PetscViewerFormat` for the output
    253: .  monitor - monitor routine, see `EPSMonitorRegisterFn`
    254: .  create  - creation routine, or `NULL`
    255: -  destroy - destruction routine, or `NULL`

    257:    Notes:
    258:    `EPSMonitorRegister()` may be called multiple times to add several user-defined monitors.

    260:    The calling sequence for the given function matches the calling sequence of `EPSMonitorFn`
    261:    functions passed to `EPSMonitorSet()` with the additional requirement that its final argument
    262:    be a `PetscViewerAndFormat`.

    264:    Example Usage:
    265: .vb
    266:    EPSMonitorRegister("my_monitor",PETSCVIEWERASCII,PETSC_VIEWER_ASCII_INFO_DETAIL,MyMonitor,NULL,NULL);
    267: .ve

    269:    Then, your monitor can be chosen with the procedural interface via
    270: .vb
    271:    EPSMonitorSetFromOptions(eps,"-eps_monitor_my_monitor","my_monitor",NULL)
    272: .ve
    273:    or at runtime via the option `-eps_monitor_my_monitor`.

    275:    Level: advanced

    277: .seealso: [](ch:eps), `EPSMonitorSet()`, `EPSMonitorRegisterAll()`, `EPSMonitorSetFromOptions()`
    278: @*/
    279: PetscErrorCode EPSMonitorRegister(const char name[],PetscViewerType vtype,PetscViewerFormat format,EPSMonitorRegisterFn *monitor,EPSMonitorRegisterCreateFn *create,EPSMonitorRegisterDestroyFn *destroy)
    280: {
    281:   char           key[PETSC_MAX_PATH_LEN];

    283:   PetscFunctionBegin;
    284:   PetscCall(EPSInitializePackage());
    285:   PetscCall(SlepcMonitorMakeKey_Internal(name,vtype,format,key));
    286:   PetscCall(PetscFunctionListAdd(&EPSMonitorList,key,monitor));
    287:   if (create)  PetscCall(PetscFunctionListAdd(&EPSMonitorCreateList,key,create));
    288:   if (destroy) PetscCall(PetscFunctionListAdd(&EPSMonitorDestroyList,key,destroy));
    289:   PetscFunctionReturn(PETSC_SUCCESS);
    290: }

    292: /*@
    293:    EPSReset - Resets the `EPS` context to the initial state (prior to setup)
    294:    and destroys any allocated `Vec`s and `Mat`s.

    296:    Collective

    298:    Input Parameter:
    299: .  eps - the linear eigensolver context

    301:    Note:
    302:    This can be used when a problem of different matrix size wants to be solved.
    303:    All options that have previously been set are preserved, so in a next use
    304:    the solver configuration is the same, but new sizes for matrices and vectors
    305:    are allowed.

    307:    Level: advanced

    309: .seealso: [](ch:eps), `EPSDestroy()`
    310: @*/
    311: PetscErrorCode EPSReset(EPS eps)
    312: {
    313:   PetscFunctionBegin;
    315:   if (!eps) PetscFunctionReturn(PETSC_SUCCESS);
    316:   PetscTryTypeMethod(eps,reset);
    317:   if (eps->st) PetscCall(STReset(eps->st));
    318:   PetscCall(VecDestroy(&eps->D));
    319:   PetscCall(BVDestroy(&eps->V));
    320:   PetscCall(BVDestroy(&eps->W));
    321:   PetscCall(VecDestroyVecs(eps->nwork,&eps->work));
    322:   eps->nwork = 0;
    323:   eps->state = EPS_STATE_INITIAL;
    324:   PetscFunctionReturn(PETSC_SUCCESS);
    325: }

    327: /*@
    328:    EPSDestroy - Destroys the `EPS` context.

    330:    Collective

    332:    Input Parameter:
    333: .  eps - the linear eigensolver context

    335:    Level: beginner

    337: .seealso: [](ch:eps), `EPSCreate()`, `EPSSetUp()`, `EPSSolve()`
    338: @*/
    339: PetscErrorCode EPSDestroy(EPS *eps)
    340: {
    341:   PetscFunctionBegin;
    342:   if (!*eps) PetscFunctionReturn(PETSC_SUCCESS);
    344:   if (--((PetscObject)*eps)->refct > 0) { *eps = NULL; PetscFunctionReturn(PETSC_SUCCESS); }
    345:   PetscCall(EPSReset(*eps));
    346:   PetscTryTypeMethod(*eps,destroy);
    347:   if ((*eps)->eigr) PetscCall(PetscFree4((*eps)->eigr,(*eps)->eigi,(*eps)->errest,(*eps)->perm));
    348:   if ((*eps)->rr) PetscCall(PetscFree2((*eps)->rr,(*eps)->ri));
    349:   PetscCall(STDestroy(&(*eps)->st));
    350:   PetscCall(RGDestroy(&(*eps)->rg));
    351:   PetscCall(DSDestroy(&(*eps)->ds));
    352:   PetscCall(PetscFree((*eps)->sc));
    353:   /* just in case the initial vectors have not been used */
    354:   PetscCall(SlepcBasisDestroy_Private(&(*eps)->nds,&(*eps)->defl));
    355:   PetscCall(SlepcBasisDestroy_Private(&(*eps)->nini,&(*eps)->IS));
    356:   PetscCall(SlepcBasisDestroy_Private(&(*eps)->ninil,&(*eps)->ISL));
    357:   if ((*eps)->convergeddestroy) PetscCall((*(*eps)->convergeddestroy)(&(*eps)->convergedctx));
    358:   if ((*eps)->stoppingdestroy) PetscCall((*(*eps)->stoppingdestroy)(&(*eps)->stoppingctx));
    359:   if ((*eps)->arbitrarydestroy) PetscCall((*(*eps)->arbitrarydestroy)(&(*eps)->arbitraryctx));
    360:   PetscCall(EPSMonitorCancel(*eps));
    361:   PetscCall(PetscHeaderDestroy(eps));
    362:   PetscFunctionReturn(PETSC_SUCCESS);
    363: }

    365: /*@
    366:    EPSSetTarget - Sets the value of the target.

    368:    Logically Collective

    370:    Input Parameters:
    371: +  eps    - the linear eigensolver context
    372: -  target - the value of the target

    374:    Options Database Key:
    375: .  -eps_target target - the value of the target

    377:    Notes:
    378:    The target is a scalar value used to determine the portion of the spectrum
    379:    of interest. It is used in combination with `EPSSetWhichEigenpairs()`.

    381:    When PETSc is built with real scalars, it is not possible to specify a
    382:    complex target.

    384:    In the case of complex scalars, a complex value can be provided in the
    385:    command line with `[+/-][realnumber][+/-]realnumberi` with no spaces, e.g.
    386:    `-eps_target 1.0+2.0i`.

    388:    Level: intermediate

    390: .seealso: [](ch:eps), `EPSGetTarget()`, `EPSSetWhichEigenpairs()`
    391: @*/
    392: PetscErrorCode EPSSetTarget(EPS eps,PetscScalar target)
    393: {
    394:   PetscFunctionBegin;
    397:   eps->target = target;
    398:   if (!eps->st) PetscCall(EPSGetST(eps,&eps->st));
    399:   PetscCall(STSetDefaultShift(eps->st,target));
    400:   PetscFunctionReturn(PETSC_SUCCESS);
    401: }

    403: /*@
    404:    EPSGetTarget - Gets the value of the target.

    406:    Not Collective

    408:    Input Parameter:
    409: .  eps - the linear eigensolver context

    411:    Output Parameter:
    412: .  target - the value of the target

    414:    Note:
    415:    If the target was not set by the user, then zero is returned.

    417:    Level: intermediate

    419: .seealso: [](ch:eps), `EPSSetTarget()`
    420: @*/
    421: PetscErrorCode EPSGetTarget(EPS eps,PetscScalar* target)
    422: {
    423:   PetscFunctionBegin;
    425:   PetscAssertPointer(target,2);
    426:   *target = eps->target;
    427:   PetscFunctionReturn(PETSC_SUCCESS);
    428: }

    430: /*@
    431:    EPSSetInterval - Defines the computational interval for spectrum slicing.

    433:    Logically Collective

    435:    Input Parameters:
    436: +  eps  - the linear eigensolver context
    437: .  inta - left end of the interval
    438: -  intb - right end of the interval

    440:    Options Database Key:
    441: .  -eps_interval a,b - set $[a,b]$ as the interval of interest

    443:    Notes:
    444:    Spectrum slicing is a technique employed for computing all eigenvalues of
    445:    symmetric eigenproblems in a given interval, see section [](#sec:slice).
    446:    This function provides the interval to be considered. It must be used in
    447:    combination with `EPS_ALL`, see `EPSSetWhichEigenpairs()`.

    449:    A computational interval is also needed when using polynomial filters,
    450:    see `STFILTER` and section [](#sec:filter).

    452:    In the command-line option, two values must be provided. For an open interval,
    453:    one can give an infinite, e.g., `-eps_interval 1.0,inf` or `-eps_interval -inf,1.0`.
    454:    An open interval in the programmatic interface can be specified with
    455:    `PETSC_MAX_REAL` and -`PETSC_MAX_REAL`.

    457:    Level: intermediate

    459: .seealso: [](ch:eps), [](#sec:slice), [](#sec:filter), `EPSGetInterval()`, `EPSSetWhichEigenpairs()`, `STFILTER`
    460: @*/
    461: PetscErrorCode EPSSetInterval(EPS eps,PetscReal inta,PetscReal intb)
    462: {
    463:   PetscFunctionBegin;
    467:   PetscCheck(inta<intb,PetscObjectComm((PetscObject)eps),PETSC_ERR_ARG_WRONG,"Badly defined interval, must be inta<intb");
    468:   if (eps->inta != inta || eps->intb != intb) {
    469:     eps->inta = inta;
    470:     eps->intb = intb;
    471:     eps->state = EPS_STATE_INITIAL;
    472:   }
    473:   PetscFunctionReturn(PETSC_SUCCESS);
    474: }

    476: /*@
    477:    EPSGetInterval - Gets the computational interval for spectrum slicing.

    479:    Not Collective

    481:    Input Parameter:
    482: .  eps - the linear eigensolver context

    484:    Output Parameters:
    485: +  inta - left end of the interval
    486: -  intb - right end of the interval

    488:    Level: intermediate

    490:    Note:
    491:    If the interval was not set by the user, then zeros are returned.

    493: .seealso: [](ch:eps), `EPSSetInterval()`
    494: @*/
    495: PetscErrorCode EPSGetInterval(EPS eps,PetscReal* inta,PetscReal* intb)
    496: {
    497:   PetscFunctionBegin;
    499:   if (inta) *inta = eps->inta;
    500:   if (intb) *intb = eps->intb;
    501:   PetscFunctionReturn(PETSC_SUCCESS);
    502: }

    504: /*@
    505:    EPSSetST - Associates a spectral transformation object to the eigensolver.

    507:    Collective

    509:    Input Parameters:
    510: +  eps - the linear eigensolver context
    511: -  st  - the spectral transformation object

    513:    Note:
    514:    Use `EPSGetST()` to retrieve the spectral transformation context at a later time
    515:    (for example, to free it at the end of the computations).

    517:    Level: advanced

    519: .seealso: [](ch:eps), `EPSGetST()`
    520: @*/
    521: PetscErrorCode EPSSetST(EPS eps,ST st)
    522: {
    523:   PetscFunctionBegin;
    526:   PetscCheckSameComm(eps,1,st,2);
    527:   PetscCall(PetscObjectReference((PetscObject)st));
    528:   PetscCall(STDestroy(&eps->st));
    529:   eps->st = st;
    530:   PetscFunctionReturn(PETSC_SUCCESS);
    531: }

    533: /*@
    534:    EPSGetST - Obtain the spectral transformation (`ST`) object associated
    535:    to the eigensolver object.

    537:    Not Collective

    539:    Input Parameter:
    540: .  eps - the linear eigensolver context

    542:    Output Parameter:
    543: .  st - spectral transformation context

    545:    Level: intermediate

    547: .seealso: [](ch:eps), `EPSSetST()`
    548: @*/
    549: PetscErrorCode EPSGetST(EPS eps,ST *st)
    550: {
    551:   PetscFunctionBegin;
    553:   PetscAssertPointer(st,2);
    554:   if (!eps->st) {
    555:     PetscCall(STCreate(PetscObjectComm((PetscObject)eps),&eps->st));
    556:     PetscCall(PetscObjectIncrementTabLevel((PetscObject)eps->st,(PetscObject)eps,0));
    557:     PetscCall(PetscObjectSetOptions((PetscObject)eps->st,((PetscObject)eps)->options));
    558:   }
    559:   *st = eps->st;
    560:   PetscFunctionReturn(PETSC_SUCCESS);
    561: }

    563: /*@
    564:    EPSSetBV - Associates a basis vectors object to the eigensolver.

    566:    Collective

    568:    Input Parameters:
    569: +  eps - the linear eigensolver context
    570: -  V   - the basis vectors object

    572:    Level: advanced

    574: .seealso: [](ch:eps), `EPSGetBV()`
    575: @*/
    576: PetscErrorCode EPSSetBV(EPS eps,BV V)
    577: {
    578:   PetscFunctionBegin;
    581:   PetscCheckSameComm(eps,1,V,2);
    582:   PetscCall(PetscObjectReference((PetscObject)V));
    583:   PetscCall(BVDestroy(&eps->V));
    584:   eps->V = V;
    585:   PetscFunctionReturn(PETSC_SUCCESS);
    586: }

    588: /*@
    589:    EPSGetBV - Obtain the basis vectors object associated to the eigensolver object.

    591:    Not Collective

    593:    Input Parameter:
    594: .  eps - the linear eigensolver context

    596:    Output Parameter:
    597: .  V - basis vectors context

    599:    Level: advanced

    601: .seealso: [](ch:eps), `EPSSetBV()`
    602: @*/
    603: PetscErrorCode EPSGetBV(EPS eps,BV *V)
    604: {
    605:   PetscFunctionBegin;
    607:   PetscAssertPointer(V,2);
    608:   if (!eps->V) {
    609:     PetscCall(BVCreate(PetscObjectComm((PetscObject)eps),&eps->V));
    610:     PetscCall(PetscObjectIncrementTabLevel((PetscObject)eps->V,(PetscObject)eps,0));
    611:     PetscCall(PetscObjectSetOptions((PetscObject)eps->V,((PetscObject)eps)->options));
    612:   }
    613:   *V = eps->V;
    614:   PetscFunctionReturn(PETSC_SUCCESS);
    615: }

    617: /*@
    618:    EPSSetRG - Associates a region object to the eigensolver.

    620:    Collective

    622:    Input Parameters:
    623: +  eps - the linear eigensolver context
    624: -  rg  - the region object

    626:    Note:
    627:    Use `EPSGetRG()` to retrieve the region context at a later time (for example,
    628:    to free it at the end of the computations).

    630:    Level: advanced

    632: .seealso: [](ch:eps), `EPSGetRG()`
    633: @*/
    634: PetscErrorCode EPSSetRG(EPS eps,RG rg)
    635: {
    636:   PetscFunctionBegin;
    638:   if (rg) {
    640:     PetscCheckSameComm(eps,1,rg,2);
    641:   }
    642:   PetscCall(PetscObjectReference((PetscObject)rg));
    643:   PetscCall(RGDestroy(&eps->rg));
    644:   eps->rg = rg;
    645:   PetscFunctionReturn(PETSC_SUCCESS);
    646: }

    648: /*@
    649:    EPSGetRG - Obtain the region object associated to the eigensolver.

    651:    Not Collective

    653:    Input Parameter:
    654: .  eps - the linear eigensolver context

    656:    Output Parameter:
    657: .  rg - region context

    659:    Level: advanced

    661: .seealso: [](ch:eps), `EPSSetRG()`
    662: @*/
    663: PetscErrorCode EPSGetRG(EPS eps,RG *rg)
    664: {
    665:   PetscFunctionBegin;
    667:   PetscAssertPointer(rg,2);
    668:   if (!eps->rg) {
    669:     PetscCall(RGCreate(PetscObjectComm((PetscObject)eps),&eps->rg));
    670:     PetscCall(PetscObjectIncrementTabLevel((PetscObject)eps->rg,(PetscObject)eps,0));
    671:     PetscCall(PetscObjectSetOptions((PetscObject)eps->rg,((PetscObject)eps)->options));
    672:   }
    673:   *rg = eps->rg;
    674:   PetscFunctionReturn(PETSC_SUCCESS);
    675: }

    677: /*@
    678:    EPSSetDS - Associates a direct solver object to the eigensolver.

    680:    Collective

    682:    Input Parameters:
    683: +  eps - the linear eigensolver context
    684: -  ds  - the direct solver object

    686:    Note:
    687:    Use `EPSGetDS()` to retrieve the direct solver context at a later time (for example,
    688:    to free it at the end of the computations).

    690:    Level: advanced

    692: .seealso: [](ch:eps), `EPSGetDS()`
    693: @*/
    694: PetscErrorCode EPSSetDS(EPS eps,DS ds)
    695: {
    696:   PetscFunctionBegin;
    699:   PetscCheckSameComm(eps,1,ds,2);
    700:   PetscCall(PetscObjectReference((PetscObject)ds));
    701:   PetscCall(DSDestroy(&eps->ds));
    702:   eps->ds = ds;
    703:   PetscFunctionReturn(PETSC_SUCCESS);
    704: }

    706: /*@
    707:    EPSGetDS - Obtain the direct solver object associated to the eigensolver object.

    709:    Not Collective

    711:    Input Parameter:
    712: .  eps - the linear eigensolver context

    714:    Output Parameter:
    715: .  ds - direct solver context

    717:    Level: advanced

    719: .seealso: [](ch:eps), `EPSSetDS()`
    720: @*/
    721: PetscErrorCode EPSGetDS(EPS eps,DS *ds)
    722: {
    723:   PetscFunctionBegin;
    725:   PetscAssertPointer(ds,2);
    726:   if (!eps->ds) {
    727:     PetscCall(DSCreate(PetscObjectComm((PetscObject)eps),&eps->ds));
    728:     PetscCall(PetscObjectIncrementTabLevel((PetscObject)eps->ds,(PetscObject)eps,0));
    729:     PetscCall(PetscObjectSetOptions((PetscObject)eps->ds,((PetscObject)eps)->options));
    730:   }
    731:   *ds = eps->ds;
    732:   PetscFunctionReturn(PETSC_SUCCESS);
    733: }

    735: /*@
    736:    EPSIsGeneralized - Ask if the `EPS` object corresponds to a generalized
    737:    eigenvalue problem.

    739:    Not Collective

    741:    Input Parameter:
    742: .  eps - the linear eigensolver context

    744:    Output Parameter:
    745: .  is - `PETSC_TRUE` if the problem is generalized

    747:    Level: intermediate

    749: .seealso: [](ch:eps), `EPSIsHermitian()`, `EPSIsPositive()`, `EPSIsStructured()`
    750: @*/
    751: PetscErrorCode EPSIsGeneralized(EPS eps,PetscBool* is)
    752: {
    753:   PetscFunctionBegin;
    755:   PetscAssertPointer(is,2);
    756:   *is = eps->isgeneralized;
    757:   PetscFunctionReturn(PETSC_SUCCESS);
    758: }

    760: /*@
    761:    EPSIsHermitian - Ask if the `EPS` object corresponds to a Hermitian
    762:    eigenvalue problem.

    764:    Not Collective

    766:    Input Parameter:
    767: .  eps - the linear eigensolver context

    769:    Output Parameter:
    770: .  is - `PETSC_TRUE` if the problem is Hermitian

    772:    Level: intermediate

    774: .seealso: [](ch:eps), `EPSIsGeneralized()`, `EPSIsPositive()`, `EPSIsStructured()`
    775: @*/
    776: PetscErrorCode EPSIsHermitian(EPS eps,PetscBool* is)
    777: {
    778:   PetscFunctionBegin;
    780:   PetscAssertPointer(is,2);
    781:   *is = eps->ishermitian;
    782:   PetscFunctionReturn(PETSC_SUCCESS);
    783: }

    785: /*@
    786:    EPSIsPositive - Ask if the `EPS` object corresponds to an eigenvalue
    787:    problem type that requires a positive (semi-) definite matrix $B$.

    789:    Not Collective

    791:    Input Parameter:
    792: .  eps - the linear eigensolver context

    794:    Output Parameter:
    795: .  is - `PETSC_TRUE` if the problem is positive (semi-) definite

    797:    Level: intermediate

    799: .seealso: [](ch:eps), `EPSIsGeneralized()`, `EPSIsHermitian()`, `EPSIsStructured()`
    800: @*/
    801: PetscErrorCode EPSIsPositive(EPS eps,PetscBool* is)
    802: {
    803:   PetscFunctionBegin;
    805:   PetscAssertPointer(is,2);
    806:   *is = eps->ispositive;
    807:   PetscFunctionReturn(PETSC_SUCCESS);
    808: }

    810: /*@
    811:    EPSIsStructured - Ask if the `EPS` object corresponds to a structured
    812:    eigenvalue problem.

    814:    Not Collective

    816:    Input Parameter:
    817: .  eps - the linear eigensolver context

    819:    Output Parameter:
    820: .  is - `PETSC_TRUE` if the problem is structured

    822:    Note:
    823:    The result will be true if the problem type has been set to some
    824:    structured type such as `EPS_BSE`. This is independent of whether the
    825:    input matrix has been built with a certain structure with a helper function.

    827:    Level: intermediate

    829: .seealso: [](ch:eps), `EPSIsGeneralized()`, `EPSIsHermitian()`, `EPSIsPositive()`, `EPSSetProblemType()`
    830: @*/
    831: PetscErrorCode EPSIsStructured(EPS eps,PetscBool* is)
    832: {
    833:   PetscFunctionBegin;
    835:   PetscAssertPointer(is,2);
    836:   *is = eps->isstructured;
    837:   PetscFunctionReturn(PETSC_SUCCESS);
    838: }