Date: 2021-02-01T14:41:54+00:00

Actual source code: epsbasic.c
slepc-3.14.2 2021-02-01
Report Typos and Errors

      1: /*
      2:    - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
      3:    SLEPc - Scalable Library for Eigenvalue Problem Computations
      4:    Copyright (c) 2002-2020, 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: PetscFunctionList EPSList = 0;
     17: PetscBool         EPSRegisterAllCalled = PETSC_FALSE;
     18: PetscClassId      EPS_CLASSID = 0;
     19: PetscLogEvent     EPS_SetUp = 0,EPS_Solve = 0;

     21: /*@
     22:    EPSCreate - Creates the default EPS context.

     24:    Collective

     26:    Input Parameter:
     27: .  comm - MPI communicator

     29:    Output Parameter:
     30: .  eps - location to put the EPS context

     32:    Note:
     33:    The default EPS type is EPSKRYLOVSCHUR

     35:    Level: beginner

     37: .seealso: EPSSetUp(), EPSSolve(), EPSDestroy(), EPS
     38: @*/
     39: PetscErrorCode EPSCreate(MPI_Comm comm,EPS *outeps)
     40: {
     42:   EPS            eps;

     46:   *outeps = 0;
     47:   EPSInitializePackage();
     48:   SlepcHeaderCreate(eps,EPS_CLASSID,"EPS","Eigenvalue Problem Solver","EPS",comm,EPSDestroy,EPSView);

     50:   eps->max_it          = PETSC_DEFAULT;
     51:   eps->nev             = 1;
     52:   eps->ncv             = PETSC_DEFAULT;
     53:   eps->mpd             = PETSC_DEFAULT;
     54:   eps->nini            = 0;
     55:   eps->nds             = 0;
     56:   eps->target          = 0.0;
     57:   eps->tol             = PETSC_DEFAULT;
     58:   eps->conv            = EPS_CONV_REL;
     59:   eps->stop            = EPS_STOP_BASIC;
     60:   eps->which           = (EPSWhich)0;
     61:   eps->inta            = 0.0;
     62:   eps->intb            = 0.0;
     63:   eps->problem_type    = (EPSProblemType)0;
     64:   eps->extraction      = EPS_RITZ;
     65:   eps->balance         = EPS_BALANCE_NONE;
     66:   eps->balance_its     = 5;
     67:   eps->balance_cutoff  = 1e-8;
     68:   eps->trueres         = PETSC_FALSE;
     69:   eps->trackall        = PETSC_FALSE;
     70:   eps->purify          = PETSC_TRUE;
     71:   eps->twosided        = PETSC_FALSE;

     73:   eps->converged       = EPSConvergedRelative;
     74:   eps->convergeduser   = NULL;
     75:   eps->convergeddestroy= NULL;
     76:   eps->stopping        = EPSStoppingBasic;
     77:   eps->stoppinguser    = NULL;
     78:   eps->stoppingdestroy = NULL;
     79:   eps->arbitrary       = NULL;
     80:   eps->convergedctx    = NULL;
     81:   eps->stoppingctx     = NULL;
     82:   eps->arbitraryctx    = NULL;
     83:   eps->numbermonitors  = 0;

     85:   eps->st              = NULL;
     86:   eps->ds              = NULL;
     87:   eps->dsts            = NULL;
     88:   eps->V               = NULL;
     89:   eps->W               = NULL;
     90:   eps->rg              = NULL;
     91:   eps->D               = NULL;
     92:   eps->IS              = NULL;
     93:   eps->ISL             = NULL;
     94:   eps->defl            = NULL;
     95:   eps->eigr            = NULL;
     96:   eps->eigi            = NULL;
     97:   eps->errest          = NULL;
     98:   eps->rr              = NULL;
     99:   eps->ri              = NULL;
    100:   eps->perm            = NULL;
    101:   eps->nwork           = 0;
    102:   eps->work            = NULL;
    103:   eps->data            = NULL;

    105:   eps->state           = EPS_STATE_INITIAL;
    106:   eps->categ           = EPS_CATEGORY_KRYLOV;
    107:   eps->nconv           = 0;
    108:   eps->its             = 0;
    109:   eps->nloc            = 0;
    110:   eps->nrma            = 0.0;
    111:   eps->nrmb            = 0.0;
    112:   eps->useds           = PETSC_FALSE;
    113:   eps->isgeneralized   = PETSC_FALSE;
    114:   eps->ispositive      = PETSC_FALSE;
    115:   eps->ishermitian     = PETSC_FALSE;
    116:   eps->reason          = EPS_CONVERGED_ITERATING;

    118:   PetscNewLog(eps,&eps->sc);
    119:   *outeps = eps;
    120:   return(0);
    121: }

    123: /*@C
    124:    EPSSetType - Selects the particular solver to be used in the EPS object.

    126:    Logically Collective on eps

    128:    Input Parameters:
    129: +  eps  - the eigensolver context
    130: -  type - a known method

    132:    Options Database Key:
    133: .  -eps_type <method> - Sets the method; use -help for a list
    134:     of available methods

    136:    Notes:
    137:    See "slepc/include/slepceps.h" for available methods. The default
    138:    is EPSKRYLOVSCHUR.

    140:    Normally, it is best to use the EPSSetFromOptions() command and
    141:    then set the EPS type from the options database rather than by using
    142:    this routine.  Using the options database provides the user with
    143:    maximum flexibility in evaluating the different available methods.
    144:    The EPSSetType() routine is provided for those situations where it
    145:    is necessary to set the iterative solver independently of the command
    146:    line or options database.

    148:    Level: intermediate

    150: .seealso: STSetType(), EPSType
    151: @*/
    152: PetscErrorCode EPSSetType(EPS eps,EPSType type)
    153: {
    154:   PetscErrorCode ierr,(*r)(EPS);
    155:   PetscBool      match;

    161:   PetscObjectTypeCompare((PetscObject)eps,type,&match);
    162:   if (match) return(0);

    164:   PetscFunctionListFind(EPSList,type,&r);
    165:   if (!r) SETERRQ1(PetscObjectComm((PetscObject)eps),PETSC_ERR_ARG_UNKNOWN_TYPE,"Unknown EPS type given: %s",type);

    167:   if (eps->ops->destroy) { (*eps->ops->destroy)(eps); }
    168:   PetscMemzero(eps->ops,sizeof(struct _EPSOps));

    170:   eps->state = EPS_STATE_INITIAL;
    171:   PetscObjectChangeTypeName((PetscObject)eps,type);
    172:   (*r)(eps);
    173:   return(0);
    174: }

    176: /*@C
    177:    EPSGetType - Gets the EPS type as a string from the EPS object.

    179:    Not Collective

    181:    Input Parameter:
    182: .  eps - the eigensolver context

    184:    Output Parameter:
    185: .  name - name of EPS method

    187:    Level: intermediate

    189: .seealso: EPSSetType()
    190: @*/
    191: PetscErrorCode EPSGetType(EPS eps,EPSType *type)
    192: {
    196:   *type = ((PetscObject)eps)->type_name;
    197:   return(0);
    198: }

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

    203:    Not Collective

    205:    Input Parameters:
    206: +  name - name of a new user-defined solver
    207: -  function - routine to create the solver context

    209:    Notes:
    210:    EPSRegister() may be called multiple times to add several user-defined solvers.

    212:    Sample usage:
    213: .vb
    214:     EPSRegister("my_solver",MySolverCreate);
    215: .ve

    217:    Then, your solver can be chosen with the procedural interface via
    218: $     EPSSetType(eps,"my_solver")
    219:    or at runtime via the option
    220: $     -eps_type my_solver

    222:    Level: advanced

    224: .seealso: EPSRegisterAll()
    225: @*/
    226: PetscErrorCode EPSRegister(const char *name,PetscErrorCode (*function)(EPS))
    227: {

    231:   EPSInitializePackage();
    232:   PetscFunctionListAdd(&EPSList,name,function);
    233:   return(0);
    234: }

    236: /*@
    237:    EPSReset - Resets the EPS context to the initial state (prior to setup)
    238:    and destroys any allocated Vecs and Mats.

    240:    Collective on eps

    242:    Input Parameter:
    243: .  eps - eigensolver context obtained from EPSCreate()

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

    251:    Level: advanced

    253: .seealso: EPSDestroy()
    254: @*/
    255: PetscErrorCode EPSReset(EPS eps)
    256: {

    261:   if (!eps) return(0);
    262:   if (eps->ops->reset) { (eps->ops->reset)(eps); }
    263:   if (eps->st) { STReset(eps->st); }
    264:   VecDestroy(&eps->D);
    265:   BVDestroy(&eps->V);
    266:   BVDestroy(&eps->W);
    267:   VecDestroyVecs(eps->nwork,&eps->work);
    268:   eps->nwork = 0;
    269:   eps->state = EPS_STATE_INITIAL;
    270:   return(0);
    271: }

    273: /*@
    274:    EPSDestroy - Destroys the EPS context.

    276:    Collective on eps

    278:    Input Parameter:
    279: .  eps - eigensolver context obtained from EPSCreate()

    281:    Level: beginner

    283: .seealso: EPSCreate(), EPSSetUp(), EPSSolve()
    284: @*/
    285: PetscErrorCode EPSDestroy(EPS *eps)
    286: {

    290:   if (!*eps) return(0);
    292:   if (--((PetscObject)(*eps))->refct > 0) { *eps = 0; return(0); }
    293:   EPSReset(*eps);
    294:   if ((*eps)->ops->destroy) { (*(*eps)->ops->destroy)(*eps); }
    295:   if ((*eps)->eigr) {
    296:     PetscFree4((*eps)->eigr,(*eps)->eigi,(*eps)->errest,(*eps)->perm);
    297:   }
    298:   if ((*eps)->rr) {
    299:     PetscFree2((*eps)->rr,(*eps)->ri);
    300:   }
    301:   STDestroy(&(*eps)->st);
    302:   RGDestroy(&(*eps)->rg);
    303:   DSDestroy(&(*eps)->ds);
    304:   DSDestroy(&(*eps)->dsts);
    305:   PetscFree((*eps)->sc);
    306:   /* just in case the initial vectors have not been used */
    307:   SlepcBasisDestroy_Private(&(*eps)->nds,&(*eps)->defl);
    308:   SlepcBasisDestroy_Private(&(*eps)->nini,&(*eps)->IS);
    309:   SlepcBasisDestroy_Private(&(*eps)->ninil,&(*eps)->ISL);
    310:   if ((*eps)->convergeddestroy) {
    311:     (*(*eps)->convergeddestroy)((*eps)->convergedctx);
    312:   }
    313:   EPSMonitorCancel(*eps);
    314:   PetscHeaderDestroy(eps);
    315:   return(0);
    316: }

    318: /*@
    319:    EPSSetTarget - Sets the value of the target.

    321:    Logically Collective on eps

    323:    Input Parameters:
    324: +  eps    - eigensolver context
    325: -  target - the value of the target

    327:    Options Database Key:
    328: .  -eps_target <scalar> - the value of the target

    330:    Notes:
    331:    The target is a scalar value used to determine the portion of the spectrum
    332:    of interest. It is used in combination with EPSSetWhichEigenpairs().

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

    338:    Level: intermediate

    340: .seealso: EPSGetTarget(), EPSSetWhichEigenpairs()
    341: @*/
    342: PetscErrorCode EPSSetTarget(EPS eps,PetscScalar target)
    343: {

    349:   eps->target = target;
    350:   if (!eps->st) { EPSGetST(eps,&eps->st); }
    351:   STSetDefaultShift(eps->st,target);
    352:   return(0);
    353: }

    355: /*@
    356:    EPSGetTarget - Gets the value of the target.

    358:    Not Collective

    360:    Input Parameter:
    361: .  eps - eigensolver context

    363:    Output Parameter:
    364: .  target - the value of the target

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

    369:    Level: intermediate

    371: .seealso: EPSSetTarget()
    372: @*/
    373: PetscErrorCode EPSGetTarget(EPS eps,PetscScalar* target)
    374: {
    378:   *target = eps->target;
    379:   return(0);
    380: }

    382: /*@
    383:    EPSSetInterval - Defines the computational interval for spectrum slicing.

    385:    Logically Collective on eps

    387:    Input Parameters:
    388: +  eps  - eigensolver context
    389: .  inta - left end of the interval
    390: -  intb - right end of the interval

    392:    Options Database Key:
    393: .  -eps_interval <a,b> - set [a,b] as the interval of interest

    395:    Notes:
    396:    Spectrum slicing is a technique employed for computing all eigenvalues of
    397:    symmetric eigenproblems in a given interval. This function provides the
    398:    interval to be considered. It must be used in combination with EPS_ALL, see
    399:    EPSSetWhichEigenpairs().

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

    406:    Level: intermediate

    408: .seealso: EPSGetInterval(), EPSSetWhichEigenpairs()
    409: @*/
    410: PetscErrorCode EPSSetInterval(EPS eps,PetscReal inta,PetscReal intb)
    411: {
    416:   if (inta>=intb) SETERRQ(PetscObjectComm((PetscObject)eps),PETSC_ERR_ARG_WRONG,"Badly defined interval, must be inta<intb");
    417:   if (eps->inta != inta || eps->intb != intb) {
    418:     eps->inta = inta;
    419:     eps->intb = intb;
    420:     eps->state = EPS_STATE_INITIAL;
    421:   }
    422:   return(0);
    423: }

    425: /*@
    426:    EPSGetInterval - Gets the computational interval for spectrum slicing.

    428:    Not Collective

    430:    Input Parameter:
    431: .  eps - eigensolver context

    433:    Output Parameters:
    434: +  inta - left end of the interval
    435: -  intb - right end of the interval

    437:    Level: intermediate

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

    442: .seealso: EPSSetInterval()
    443: @*/
    444: PetscErrorCode EPSGetInterval(EPS eps,PetscReal* inta,PetscReal* intb)
    445: {
    448:   if (inta) *inta = eps->inta;
    449:   if (intb) *intb = eps->intb;
    450:   return(0);
    451: }

    453: /*@
    454:    EPSSetST - Associates a spectral transformation object to the eigensolver.

    456:    Collective on eps

    458:    Input Parameters:
    459: +  eps - eigensolver context obtained from EPSCreate()
    460: -  st   - the spectral transformation object

    462:    Note:
    463:    Use EPSGetST() to retrieve the spectral transformation context (for example,
    464:    to free it at the end of the computations).

    466:    Level: advanced

    468: .seealso: EPSGetST()
    469: @*/
    470: PetscErrorCode EPSSetST(EPS eps,ST st)
    471: {

    478:   PetscObjectReference((PetscObject)st);
    479:   STDestroy(&eps->st);
    480:   eps->st = st;
    481:   PetscLogObjectParent((PetscObject)eps,(PetscObject)eps->st);
    482:   return(0);
    483: }

    485: /*@
    486:    EPSGetST - Obtain the spectral transformation (ST) object associated
    487:    to the eigensolver object.

    489:    Not Collective

    491:    Input Parameters:
    492: .  eps - eigensolver context obtained from EPSCreate()

    494:    Output Parameter:
    495: .  st - spectral transformation context

    497:    Level: intermediate

    499: .seealso: EPSSetST()
    500: @*/
    501: PetscErrorCode EPSGetST(EPS eps,ST *st)
    502: {

    508:   if (!eps->st) {
    509:     STCreate(PetscObjectComm((PetscObject)eps),&eps->st);
    510:     PetscObjectIncrementTabLevel((PetscObject)eps->st,(PetscObject)eps,0);
    511:     PetscLogObjectParent((PetscObject)eps,(PetscObject)eps->st);
    512:     PetscObjectSetOptions((PetscObject)eps->st,((PetscObject)eps)->options);
    513:   }
    514:   *st = eps->st;
    515:   return(0);
    516: }

    518: /*@
    519:    EPSSetBV - Associates a basis vectors object to the eigensolver.

    521:    Collective on eps

    523:    Input Parameters:
    524: +  eps - eigensolver context obtained from EPSCreate()
    525: -  V   - the basis vectors object

    527:    Level: advanced

    529: .seealso: EPSGetBV()
    530: @*/
    531: PetscErrorCode EPSSetBV(EPS eps,BV V)
    532: {

    539:   PetscObjectReference((PetscObject)V);
    540:   BVDestroy(&eps->V);
    541:   eps->V = V;
    542:   PetscLogObjectParent((PetscObject)eps,(PetscObject)eps->V);
    543:   return(0);
    544: }

    546: /*@
    547:    EPSGetBV - Obtain the basis vectors object associated to the eigensolver object.

    549:    Not Collective

    551:    Input Parameters:
    552: .  eps - eigensolver context obtained from EPSCreate()

    554:    Output Parameter:
    555: .  V - basis vectors context

    557:    Level: advanced

    559: .seealso: EPSSetBV()
    560: @*/
    561: PetscErrorCode EPSGetBV(EPS eps,BV *V)
    562: {

    568:   if (!eps->V) {
    569:     BVCreate(PetscObjectComm((PetscObject)eps),&eps->V);
    570:     PetscObjectIncrementTabLevel((PetscObject)eps->V,(PetscObject)eps,0);
    571:     PetscLogObjectParent((PetscObject)eps,(PetscObject)eps->V);
    572:     PetscObjectSetOptions((PetscObject)eps->V,((PetscObject)eps)->options);
    573:   }
    574:   *V = eps->V;
    575:   return(0);
    576: }

    578: /*@
    579:    EPSSetRG - Associates a region object to the eigensolver.

    581:    Collective on eps

    583:    Input Parameters:
    584: +  eps - eigensolver context obtained from EPSCreate()
    585: -  rg  - the region object

    587:    Note:
    588:    Use EPSGetRG() to retrieve the region context (for example,
    589:    to free it at the end of the computations).

    591:    Level: advanced

    593: .seealso: EPSGetRG()
    594: @*/
    595: PetscErrorCode EPSSetRG(EPS eps,RG rg)
    596: {

    603:   PetscObjectReference((PetscObject)rg);
    604:   RGDestroy(&eps->rg);
    605:   eps->rg = rg;
    606:   PetscLogObjectParent((PetscObject)eps,(PetscObject)eps->rg);
    607:   return(0);
    608: }

    610: /*@
    611:    EPSGetRG - Obtain the region object associated to the eigensolver.

    613:    Not Collective

    615:    Input Parameters:
    616: .  eps - eigensolver context obtained from EPSCreate()

    618:    Output Parameter:
    619: .  rg - region context

    621:    Level: advanced

    623: .seealso: EPSSetRG()
    624: @*/
    625: PetscErrorCode EPSGetRG(EPS eps,RG *rg)
    626: {

    632:   if (!eps->rg) {
    633:     RGCreate(PetscObjectComm((PetscObject)eps),&eps->rg);
    634:     PetscObjectIncrementTabLevel((PetscObject)eps->rg,(PetscObject)eps,0);
    635:     PetscLogObjectParent((PetscObject)eps,(PetscObject)eps->rg);
    636:     PetscObjectSetOptions((PetscObject)eps->rg,((PetscObject)eps)->options);
    637:   }
    638:   *rg = eps->rg;
    639:   return(0);
    640: }

    642: /*@
    643:    EPSSetDS - Associates a direct solver object to the eigensolver.

    645:    Collective on eps

    647:    Input Parameters:
    648: +  eps - eigensolver context obtained from EPSCreate()
    649: -  ds  - the direct solver object

    651:    Note:
    652:    Use EPSGetDS() to retrieve the direct solver context (for example,
    653:    to free it at the end of the computations).

    655:    Level: advanced

    657: .seealso: EPSGetDS()
    658: @*/
    659: PetscErrorCode EPSSetDS(EPS eps,DS ds)
    660: {

    667:   PetscObjectReference((PetscObject)ds);
    668:   DSDestroy(&eps->ds);
    669:   eps->ds = ds;
    670:   PetscLogObjectParent((PetscObject)eps,(PetscObject)eps->ds);
    671:   return(0);
    672: }

    674: /*@
    675:    EPSGetDS - Obtain the direct solver object associated to the eigensolver object.

    677:    Not Collective

    679:    Input Parameters:
    680: .  eps - eigensolver context obtained from EPSCreate()

    682:    Output Parameter:
    683: .  ds - direct solver context

    685:    Level: advanced

    687: .seealso: EPSSetDS()
    688: @*/
    689: PetscErrorCode EPSGetDS(EPS eps,DS *ds)
    690: {

    696:   if (!eps->ds) {
    697:     DSCreate(PetscObjectComm((PetscObject)eps),&eps->ds);
    698:     PetscObjectIncrementTabLevel((PetscObject)eps->ds,(PetscObject)eps,0);
    699:     PetscLogObjectParent((PetscObject)eps,(PetscObject)eps->ds);
    700:     PetscObjectSetOptions((PetscObject)eps->ds,((PetscObject)eps)->options);
    701:   }
    702:   *ds = eps->ds;
    703:   return(0);
    704: }

    706: /*@
    707:    EPSIsGeneralized - Ask if the EPS object corresponds to a generalized
    708:    eigenvalue problem.

    710:    Not collective

    712:    Input Parameter:
    713: .  eps - the eigenproblem solver context

    715:    Output Parameter:
    716: .  is - the answer

    718:    Level: intermediate

    720: .seealso: EPSIsHermitian(), EPSIsPositive()
    721: @*/
    722: PetscErrorCode EPSIsGeneralized(EPS eps,PetscBool* is)
    723: {
    727:   *is = eps->isgeneralized;
    728:   return(0);
    729: }

    731: /*@
    732:    EPSIsHermitian - Ask if the EPS object corresponds to a Hermitian
    733:    eigenvalue problem.

    735:    Not collective

    737:    Input Parameter:
    738: .  eps - the eigenproblem solver context

    740:    Output Parameter:
    741: .  is - the answer

    743:    Level: intermediate

    745: .seealso: EPSIsGeneralized(), EPSIsPositive()
    746: @*/
    747: PetscErrorCode EPSIsHermitian(EPS eps,PetscBool* is)
    748: {
    752:   *is = eps->ishermitian;
    753:   return(0);
    754: }

    756: /*@
    757:    EPSIsPositive - Ask if the EPS object corresponds to an eigenvalue
    758:    problem type that requires a positive (semi-) definite matrix B.

    760:    Not collective

    762:    Input Parameter:
    763: .  eps - the eigenproblem solver context

    765:    Output Parameter:
    766: .  is - the answer

    768:    Level: intermediate

    770: .seealso: EPSIsGeneralized(), EPSIsHermitian()
    771: @*/
    772: PetscErrorCode EPSIsPositive(EPS eps,PetscBool* is)
    773: {
    777:   *is = eps->ispositive;
    778:   return(0);
    779: }