Date: 2026-03-09T09:12:30+00:00

Actual source code: jd.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:    SLEPc eigensolver: "jd"

     13:    Method: Jacobi-Davidson

     15:    Algorithm:

     17:        Jacobi-Davidson with various subspace extraction and
     18:        restart techniques.

     20:    References:

     22:        [1] G.L.G. Sleijpen and H.A. van der Vorst, "A Jacobi-Davidson
     23:            iteration method for linear eigenvalue problems", SIAM J.
     24:            Matrix Anal. Appl. 17(2):401-425, 1996.

     26:        [2] E. Romero and J.E. Roman, "A parallel implementation of
     27:            Davidson methods for large-scale eigenvalue problems in
     28:            SLEPc", ACM Trans. Math. Software 40(2), Article 13, 2014.
     29: */

     31: #include <slepc/private/epsimpl.h>
     32: #include <../src/eps/impls/davidson/davidson.h>

     34: static PetscErrorCode EPSSetFromOptions_JD(EPS eps,PetscOptionItems PetscOptionsObject)
     35: {
     36:   PetscBool      flg,flg2,op,orth;
     37:   PetscInt       opi,opi0;
     38:   PetscReal      opf;

     40:   PetscFunctionBegin;
     41:   PetscOptionsHeadBegin(PetscOptionsObject,"EPS Jacobi-Davidson (JD) Options");

     43:     PetscCall(EPSJDGetKrylovStart(eps,&op));
     44:     PetscCall(PetscOptionsBool("-eps_jd_krylov_start","Start the search subspace with a Krylov basis","EPSJDSetKrylovStart",op,&op,&flg));
     45:     if (flg) PetscCall(EPSJDSetKrylovStart(eps,op));

     47:     PetscCall(EPSJDGetBOrth(eps,&orth));
     48:     PetscCall(PetscOptionsBool("-eps_jd_borth","Use B-orthogonalization in the search subspace","EPSJDSetBOrth",op,&op,&flg));
     49:     if (flg) PetscCall(EPSJDSetBOrth(eps,op));

     51:     PetscCall(EPSJDGetBlockSize(eps,&opi));
     52:     PetscCall(PetscOptionsInt("-eps_jd_blocksize","Number of vectors to add to the search subspace","EPSJDSetBlockSize",opi,&opi,&flg));
     53:     if (flg) PetscCall(EPSJDSetBlockSize(eps,opi));

     55:     PetscCall(EPSJDGetRestart(eps,&opi,&opi0));
     56:     PetscCall(PetscOptionsInt("-eps_jd_minv","Size of the search subspace after restarting","EPSJDSetRestart",opi,&opi,&flg));
     57:     PetscCall(PetscOptionsInt("-eps_jd_plusk","Number of eigenvectors saved from the previous iteration when restarting","EPSJDSetRestart",opi0,&opi0,&flg2));
     58:     if (flg || flg2) PetscCall(EPSJDSetRestart(eps,opi,opi0));

     60:     PetscCall(EPSJDGetInitialSize(eps,&opi));
     61:     PetscCall(PetscOptionsInt("-eps_jd_initial_size","Initial size of the search subspace","EPSJDSetInitialSize",opi,&opi,&flg));
     62:     if (flg) PetscCall(EPSJDSetInitialSize(eps,opi));

     64:     PetscCall(EPSJDGetFix(eps,&opf));
     65:     PetscCall(PetscOptionsReal("-eps_jd_fix","Tolerance for changing the target in the correction equation","EPSJDSetFix",opf,&opf,&flg));
     66:     if (flg) PetscCall(EPSJDSetFix(eps,opf));

     68:     PetscCall(EPSJDGetConstCorrectionTol(eps,&op));
     69:     PetscCall(PetscOptionsBool("-eps_jd_const_correction_tol","Disable the dynamic stopping criterion when solving the correction equation","EPSJDSetConstCorrectionTol",op,&op,&flg));
     70:     if (flg) PetscCall(EPSJDSetConstCorrectionTol(eps,op));

     72:   PetscOptionsHeadEnd();
     73:   PetscFunctionReturn(PETSC_SUCCESS);
     74: }

     76: static PetscErrorCode EPSSetDefaultST_JD(EPS eps)
     77: {
     78:   KSP            ksp;

     80:   PetscFunctionBegin;
     81:   if (!((PetscObject)eps->st)->type_name) {
     82:     PetscCall(STSetType(eps->st,STPRECOND));
     83:     PetscCall(STPrecondSetKSPHasMat(eps->st,PETSC_TRUE));
     84:   }
     85:   PetscCall(STGetKSP(eps->st,&ksp));
     86:   if (!((PetscObject)ksp)->type_name) {
     87:     PetscCall(KSPSetType(ksp,KSPBCGSL));
     88:     PetscCall(KSPSetTolerances(ksp,1e-4,PETSC_CURRENT,PETSC_CURRENT,90));
     89:   }
     90:   PetscFunctionReturn(PETSC_SUCCESS);
     91: }

     93: static PetscErrorCode EPSSetUp_JD(EPS eps)
     94: {
     95:   PetscBool      t;
     96:   KSP            ksp;

     98:   PetscFunctionBegin;
     99:   /* Setup common for all davidson solvers */
    100:   PetscCall(EPSSetUp_XD(eps));

    102:   /* Check some constraints */
    103:   PetscCall(STGetKSP(eps->st,&ksp));
    104:   PetscCall(PetscObjectTypeCompare((PetscObject)ksp,KSPPREONLY,&t));
    105:   PetscCheck(!t,PetscObjectComm((PetscObject)eps),PETSC_ERR_SUP,"EPSJD does not work with KSPPREONLY");
    106:   PetscFunctionReturn(PETSC_SUCCESS);
    107: }

    109: static PetscErrorCode EPSView_JD(EPS eps,PetscViewer viewer)
    110: {
    111:   PetscBool      isascii,opb;
    112:   PetscReal      opf;
    113:   PetscInt       opi,opi0;

    115:   PetscFunctionBegin;
    116:   PetscCall(PetscObjectTypeCompare((PetscObject)viewer,PETSCVIEWERASCII,&isascii));
    117:   if (isascii) {
    118:     PetscCall(EPSXDGetBOrth_XD(eps,&opb));
    119:     if (opb) PetscCall(PetscViewerASCIIPrintf(viewer,"  search subspace is B-orthogonalized\n"));
    120:     else PetscCall(PetscViewerASCIIPrintf(viewer,"  search subspace is orthogonalized\n"));
    121:     PetscCall(EPSXDGetBlockSize_XD(eps,&opi));
    122:     PetscCall(PetscViewerASCIIPrintf(viewer,"  block size=%" PetscInt_FMT "\n",opi));
    123:     PetscCall(EPSXDGetKrylovStart_XD(eps,&opb));
    124:     if (!opb) PetscCall(PetscViewerASCIIPrintf(viewer,"  type of the initial subspace: non-Krylov\n"));
    125:     else PetscCall(PetscViewerASCIIPrintf(viewer,"  type of the initial subspace: Krylov\n"));
    126:     PetscCall(EPSXDGetRestart_XD(eps,&opi,&opi0));
    127:     PetscCall(PetscViewerASCIIPrintf(viewer,"  size of the subspace after restarting: %" PetscInt_FMT "\n",opi));
    128:     PetscCall(PetscViewerASCIIPrintf(viewer,"  number of vectors after restarting from the previous iteration: %" PetscInt_FMT "\n",opi0));

    130:     PetscCall(EPSJDGetFix_JD(eps,&opf));
    131:     PetscCall(PetscViewerASCIIPrintf(viewer,"  threshold for changing the target in the correction equation (fix): %g\n",(double)opf));

    133:     PetscCall(EPSJDGetConstCorrectionTol_JD(eps,&opb));
    134:     if (!opb) PetscCall(PetscViewerASCIIPrintf(viewer,"  using dynamic tolerance for the correction equation\n"));
    135:   }
    136:   PetscFunctionReturn(PETSC_SUCCESS);
    137: }

    139: static PetscErrorCode EPSDestroy_JD(EPS eps)
    140: {
    141:   PetscFunctionBegin;
    142:   PetscCall(PetscFree(eps->data));
    143:   PetscCall(PetscObjectComposeFunction((PetscObject)eps,"EPSJDSetKrylovStart_C",NULL));
    144:   PetscCall(PetscObjectComposeFunction((PetscObject)eps,"EPSJDGetKrylovStart_C",NULL));
    145:   PetscCall(PetscObjectComposeFunction((PetscObject)eps,"EPSJDSetBlockSize_C",NULL));
    146:   PetscCall(PetscObjectComposeFunction((PetscObject)eps,"EPSJDGetBlockSize_C",NULL));
    147:   PetscCall(PetscObjectComposeFunction((PetscObject)eps,"EPSJDSetRestart_C",NULL));
    148:   PetscCall(PetscObjectComposeFunction((PetscObject)eps,"EPSJDGetRestart_C",NULL));
    149:   PetscCall(PetscObjectComposeFunction((PetscObject)eps,"EPSJDSetInitialSize_C",NULL));
    150:   PetscCall(PetscObjectComposeFunction((PetscObject)eps,"EPSJDGetInitialSize_C",NULL));
    151:   PetscCall(PetscObjectComposeFunction((PetscObject)eps,"EPSJDSetFix_C",NULL));
    152:   PetscCall(PetscObjectComposeFunction((PetscObject)eps,"EPSJDGetFix_C",NULL));
    153:   PetscCall(PetscObjectComposeFunction((PetscObject)eps,"EPSJDSetConstCorrectionTol_C",NULL));
    154:   PetscCall(PetscObjectComposeFunction((PetscObject)eps,"EPSJDGetConstCorrectionTol_C",NULL));
    155:   PetscCall(PetscObjectComposeFunction((PetscObject)eps,"EPSJDSetBOrth_C",NULL));
    156:   PetscCall(PetscObjectComposeFunction((PetscObject)eps,"EPSJDGetBOrth_C",NULL));
    157:   PetscFunctionReturn(PETSC_SUCCESS);
    158: }

    160: /*@
    161:    EPSJDSetKrylovStart - Activates or deactivates starting the searching
    162:    subspace with a Krylov basis.

    164:    Logically Collective

    166:    Input Parameters:
    167: +  eps         - the linear eigensolver context
    168: -  krylovstart - boolean flag

    170:    Options Database Key:
    171: .  -eps_jd_krylov_start - activate starting the searching subspace with a Krylov basis

    173:    Note:
    174:    See discussion at `EPSJDSetInitialSize()`.

    176:    Level: advanced

    178: .seealso: [](ch:eps), `EPSJD`, `EPSJDGetKrylovStart()`
    179: @*/
    180: PetscErrorCode EPSJDSetKrylovStart(EPS eps,PetscBool krylovstart)
    181: {
    182:   PetscFunctionBegin;
    185:   PetscTryMethod(eps,"EPSJDSetKrylovStart_C",(EPS,PetscBool),(eps,krylovstart));
    186:   PetscFunctionReturn(PETSC_SUCCESS);
    187: }

    189: /*@
    190:    EPSJDGetKrylovStart - Returns a flag indicating if the searching subspace is started with a
    191:    Krylov basis.

    193:    Not Collective

    195:    Input Parameter:
    196: .  eps - the linear eigensolver context

    198:    Output Parameter:
    199: .  krylovstart - boolean flag indicating if the searching subspace is started with a Krylov basis

    201:    Level: advanced

    203: .seealso: [](ch:eps), `EPSJD`, `EPSJDSetKrylovStart()`
    204: @*/
    205: PetscErrorCode EPSJDGetKrylovStart(EPS eps,PetscBool *krylovstart)
    206: {
    207:   PetscFunctionBegin;
    209:   PetscAssertPointer(krylovstart,2);
    210:   PetscUseMethod(eps,"EPSJDGetKrylovStart_C",(EPS,PetscBool*),(eps,krylovstart));
    211:   PetscFunctionReturn(PETSC_SUCCESS);
    212: }

    214: /*@
    215:    EPSJDSetBlockSize - Sets the number of vectors to be added to the searching space
    216:    in every iteration.

    218:    Logically Collective

    220:    Input Parameters:
    221: +  eps       - the linear eigensolver context
    222: -  blocksize - number of vectors added to the search space in every iteration

    224:    Options Database Key:
    225: .  -eps_jd_blocksize \<blocksize\> - number of vectors added to the search space in every iteration

    227:    Note:
    228:    Detailed information can be found at {cite:p}`Rom14`.

    230:    Level: advanced

    232: .seealso: [](ch:eps), `EPSJD`, `EPSJDSetKrylovStart()`
    233: @*/
    234: PetscErrorCode EPSJDSetBlockSize(EPS eps,PetscInt blocksize)
    235: {
    236:   PetscFunctionBegin;
    239:   PetscTryMethod(eps,"EPSJDSetBlockSize_C",(EPS,PetscInt),(eps,blocksize));
    240:   PetscFunctionReturn(PETSC_SUCCESS);
    241: }

    243: /*@
    244:    EPSJDGetBlockSize - Returns the number of vectors to be added to the searching space
    245:    in every iteration.

    247:    Not Collective

    249:    Input Parameter:
    250: .  eps - the linear eigensolver context

    252:    Output Parameter:
    253: .  blocksize - number of vectors added to the search space in every iteration

    255:    Level: advanced

    257: .seealso: [](ch:eps), `EPSJD`, `EPSJDSetBlockSize()`
    258: @*/
    259: PetscErrorCode EPSJDGetBlockSize(EPS eps,PetscInt *blocksize)
    260: {
    261:   PetscFunctionBegin;
    263:   PetscAssertPointer(blocksize,2);
    264:   PetscUseMethod(eps,"EPSJDGetBlockSize_C",(EPS,PetscInt*),(eps,blocksize));
    265:   PetscFunctionReturn(PETSC_SUCCESS);
    266: }

    268: /*@
    269:    EPSJDSetRestart - Sets the number of vectors of the searching space after
    270:    restarting and the number of vectors saved from the previous iteration.

    272:    Logically Collective

    274:    Input Parameters:
    275: +  eps   - the linear eigensolver context
    276: .  minv  - number of vectors of the searching subspace after restarting
    277: -  plusk - number of vectors saved from the previous iteration

    279:    Options Database Keys:
    280: +  -eps_jd_minv \<minv\>   - number of vectors of the searching subspace after restarting
    281: -  -eps_jd_plusk \<plusk\> - number of vectors saved from the previous iteration

    283:    Notes:
    284:    `PETSC_CURRENT` can be used to preserve the current value of any of the
    285:    arguments, and `PETSC_DETERMINE` to set them to a default value.

    287:    Detailed information can be found at {cite:p}`Rom14`.

    289:    Level: advanced

    291: .seealso: [](ch:eps), `EPSJD`, `EPSJDGetRestart()`
    292: @*/
    293: PetscErrorCode EPSJDSetRestart(EPS eps,PetscInt minv,PetscInt plusk)
    294: {
    295:   PetscFunctionBegin;
    299:   PetscTryMethod(eps,"EPSJDSetRestart_C",(EPS,PetscInt,PetscInt),(eps,minv,plusk));
    300:   PetscFunctionReturn(PETSC_SUCCESS);
    301: }

    303: /*@
    304:    EPSJDGetRestart - Gets the number of vectors of the searching space after
    305:    restarting and the number of vectors saved from the previous iteration.

    307:    Not Collective

    309:    Input Parameter:
    310: .  eps - the linear eigensolver context

    312:    Output Parameters:
    313: +  minv  - number of vectors of the searching subspace after restarting
    314: -  plusk - number of vectors saved from the previous iteration

    316:    Level: advanced

    318: .seealso: [](ch:eps), `EPSJD`, `EPSJDSetRestart()`
    319: @*/
    320: PetscErrorCode EPSJDGetRestart(EPS eps,PetscInt *minv,PetscInt *plusk)
    321: {
    322:   PetscFunctionBegin;
    324:   PetscUseMethod(eps,"EPSJDGetRestart_C",(EPS,PetscInt*,PetscInt*),(eps,minv,plusk));
    325:   PetscFunctionReturn(PETSC_SUCCESS);
    326: }

    328: /*@
    329:    EPSJDSetInitialSize - Sets the initial size of the searching space.

    331:    Logically Collective

    333:    Input Parameters:
    334: +  eps         - the linear eigensolver context
    335: -  initialsize - number of vectors of the initial searching subspace

    337:    Options Database Key:
    338: .  -eps_jd_initial_size \<initialsize\> - number of vectors of the initial searching subspace

    340:    Notes:
    341:    If the flag in `EPSJDSetKrylovStart()` is set to `PETSC_FALSE` and the user
    342:    provides vectors with `EPSSetInitialSpace()`, up to `initialsize` vectors will be used;
    343:    and if the provided vectors are not enough, the solver completes the subspace with
    344:    random vectors. In case the `EPSJDSetKrylovStart()` flag is `PETSC_TRUE`, the solver
    345:    gets the first vector provided by the user or, if not available, a random vector,
    346:    and expands the Krylov basis up to `initialsize` vectors.

    348:    Detailed information can be found at {cite:p}`Rom14`.

    350:    Level: advanced

    352: .seealso: [](ch:eps), `EPSJD`, `EPSJDGetInitialSize()`, `EPSJDGetKrylovStart()`
    353: @*/
    354: PetscErrorCode EPSJDSetInitialSize(EPS eps,PetscInt initialsize)
    355: {
    356:   PetscFunctionBegin;
    359:   PetscTryMethod(eps,"EPSJDSetInitialSize_C",(EPS,PetscInt),(eps,initialsize));
    360:   PetscFunctionReturn(PETSC_SUCCESS);
    361: }

    363: /*@
    364:    EPSJDGetInitialSize - Returns the initial size of the searching space.

    366:    Not Collective

    368:    Input Parameter:
    369: .  eps - the linear eigensolver context

    371:    Output Parameter:
    372: .  initialsize - number of vectors of the initial searching subspace

    374:    Level: advanced

    376: .seealso: [](ch:eps), `EPSJD`, `EPSJDSetInitialSize()`, `EPSJDGetKrylovStart()`
    377: @*/
    378: PetscErrorCode EPSJDGetInitialSize(EPS eps,PetscInt *initialsize)
    379: {
    380:   PetscFunctionBegin;
    382:   PetscAssertPointer(initialsize,2);
    383:   PetscUseMethod(eps,"EPSJDGetInitialSize_C",(EPS,PetscInt*),(eps,initialsize));
    384:   PetscFunctionReturn(PETSC_SUCCESS);
    385: }

    387: static PetscErrorCode EPSJDSetFix_JD(EPS eps,PetscReal fix)
    388: {
    389:   EPS_DAVIDSON *data = (EPS_DAVIDSON*)eps->data;

    391:   PetscFunctionBegin;
    392:   if (fix == (PetscReal)PETSC_DEFAULT || fix == (PetscReal)PETSC_DECIDE) fix = 0.01;
    393:   PetscCheck(fix>0.0,PetscObjectComm((PetscObject)eps),PETSC_ERR_ARG_OUTOFRANGE,"Invalid fix value, must be >0");
    394:   data->fix = fix;
    395:   PetscFunctionReturn(PETSC_SUCCESS);
    396: }

    398: /*@
    399:    EPSJDSetFix - Sets the threshold for changing the target in the correction
    400:    equation.

    402:    Logically Collective

    404:    Input Parameters:
    405: +  eps - the linear eigensolver context
    406: -  fix - threshold for changing the target

    408:    Options Database Key:
    409: .  -eps_jd_fix \<fix\> - the fix value

    411:    Notes:
    412:    The target in the correction equation is fixed at the first iterations.
    413:    When the norm of the residual vector is lower than the `fix` value,
    414:    the target is set to the corresponding eigenvalue.

    416:    Detailed information can be found at {cite:p}`Rom14`.

    418:    Level: advanced

    420: .seealso: [](ch:eps), `EPSJD`, `EPSJDGetFix()`
    421: @*/
    422: PetscErrorCode EPSJDSetFix(EPS eps,PetscReal fix)
    423: {
    424:   PetscFunctionBegin;
    427:   PetscTryMethod(eps,"EPSJDSetFix_C",(EPS,PetscReal),(eps,fix));
    428:   PetscFunctionReturn(PETSC_SUCCESS);
    429: }

    431: PetscErrorCode EPSJDGetFix_JD(EPS eps,PetscReal *fix)
    432: {
    433:   EPS_DAVIDSON *data = (EPS_DAVIDSON*)eps->data;

    435:   PetscFunctionBegin;
    436:   *fix = data->fix;
    437:   PetscFunctionReturn(PETSC_SUCCESS);
    438: }

    440: /*@
    441:    EPSJDGetFix - Returns the threshold for changing the target in the correction
    442:    equation.

    444:    Not Collective

    446:    Input Parameter:
    447: .  eps - the linear eigensolver context

    449:    Output Parameter:
    450: .  fix - threshold for changing the target

    452:    Level: advanced

    454: .seealso: [](ch:eps), `EPSJD`, `EPSJDSetFix()`
    455: @*/
    456: PetscErrorCode EPSJDGetFix(EPS eps,PetscReal *fix)
    457: {
    458:   PetscFunctionBegin;
    460:   PetscAssertPointer(fix,2);
    461:   PetscUseMethod(eps,"EPSJDGetFix_C",(EPS,PetscReal*),(eps,fix));
    462:   PetscFunctionReturn(PETSC_SUCCESS);
    463: }

    465: static PetscErrorCode EPSJDSetConstCorrectionTol_JD(EPS eps,PetscBool constant)
    466: {
    467:   EPS_DAVIDSON *data = (EPS_DAVIDSON*)eps->data;

    469:   PetscFunctionBegin;
    470:   data->dynamic = PetscNot(constant);
    471:   PetscFunctionReturn(PETSC_SUCCESS);
    472: }

    474: /*@
    475:    EPSJDSetConstCorrectionTol - Deactivate the dynamic stopping criterion
    476:    (also called Newton).

    478:    Logically Collective

    480:    Input Parameters:
    481: +  eps - the linear eigensolver context
    482: -  constant - if `PETSC_FALSE`, the `KSP` relative tolerance is set to $2^{-i}$

    484:    Options Database Key:
    485: .  -eps_jd_const_correction_tol - set a constant or dynamic stopping criterion

    487:    Notes:
    488:    If this flag is set to `PETSC_FALSE`, then the `KSP` relative tolerance is
    489:    dynamically set to $2^{-i}$, where $i$ is the number of `EPS` iterations
    490:    since the last converged eigenvalue. By the default, a constant tolerance is used.

    492:    Detailed information can be found at {cite:p}`Rom14`.

    494:    Level: advanced

    496: .seealso: [](ch:eps), `EPSJD`, `EPSJDGetConstCorrectionTol()`
    497: @*/
    498: PetscErrorCode EPSJDSetConstCorrectionTol(EPS eps,PetscBool constant)
    499: {
    500:   PetscFunctionBegin;
    503:   PetscTryMethod(eps,"EPSJDSetConstCorrectionTol_C",(EPS,PetscBool),(eps,constant));
    504:   PetscFunctionReturn(PETSC_SUCCESS);
    505: }

    507: PetscErrorCode EPSJDGetConstCorrectionTol_JD(EPS eps,PetscBool *constant)
    508: {
    509:   EPS_DAVIDSON *data = (EPS_DAVIDSON*)eps->data;

    511:   PetscFunctionBegin;
    512:   *constant = PetscNot(data->dynamic);
    513:   PetscFunctionReturn(PETSC_SUCCESS);
    514: }

    516: /*@
    517:    EPSJDGetConstCorrectionTol - Returns a flag indicating if a constant
    518:    of dynamic stopping is being used for solving the correction equation.

    520:    Not Collective

    522:    Input Parameter:
    523: .  eps - the linear eigensolver context

    525:    Output Parameter:
    526: .  constant - boolean flag indicating if a constant or dynamic stopping criterion is used

    528:    Level: advanced

    530: .seealso: [](ch:eps), `EPSJD`, `EPSJDSetConstCorrectionTol()`
    531: @*/
    532: PetscErrorCode EPSJDGetConstCorrectionTol(EPS eps,PetscBool *constant)
    533: {
    534:   PetscFunctionBegin;
    536:   PetscAssertPointer(constant,2);
    537:   PetscUseMethod(eps,"EPSJDGetConstCorrectionTol_C",(EPS,PetscBool*),(eps,constant));
    538:   PetscFunctionReturn(PETSC_SUCCESS);
    539: }

    541: /*@
    542:    EPSJDSetBOrth - Selects the orthogonalization that will be used in the search
    543:    subspace in case of generalized Hermitian problems.

    545:    Logically Collective

    547:    Input Parameters:
    548: +  eps   - the linear eigensolver context
    549: -  borth - whether to $B$-orthogonalize the search subspace

    551:    Options Database Key:
    552: .  -eps_jd_borth - toggle the $B$-orthogonalization

    554:    Note:
    555:    Detailed information can be found at {cite:p}`Rom14`.

    557:    Level: advanced

    559: .seealso: [](ch:eps), `EPSJD`, `EPSJDGetBOrth()`
    560: @*/
    561: PetscErrorCode EPSJDSetBOrth(EPS eps,PetscBool borth)
    562: {
    563:   PetscFunctionBegin;
    566:   PetscTryMethod(eps,"EPSJDSetBOrth_C",(EPS,PetscBool),(eps,borth));
    567:   PetscFunctionReturn(PETSC_SUCCESS);
    568: }

    570: /*@
    571:    EPSJDGetBOrth - Returns the orthogonalization used in the search
    572:    subspace in case of generalized Hermitian problems.

    574:    Not Collective

    576:    Input Parameter:
    577: .  eps - the linear eigensolver context

    579:    Output Parameter:
    580: .  borth - whether to $B$-orthogonalize the search subspace

    582:    Level: advanced

    584: .seealso: [](ch:eps), `EPSJD`, `EPSJDSetBOrth()`
    585: @*/
    586: PetscErrorCode EPSJDGetBOrth(EPS eps,PetscBool *borth)
    587: {
    588:   PetscFunctionBegin;
    590:   PetscAssertPointer(borth,2);
    591:   PetscUseMethod(eps,"EPSJDGetBOrth_C",(EPS,PetscBool*),(eps,borth));
    592:   PetscFunctionReturn(PETSC_SUCCESS);
    593: }

    595: /*MC
    596:    EPSJD - EPSJD = "jd" - The Jacobi-Davidson method.

    598:    Notes:
    599:    This is a preconditioned eigensolver, that is, it may be competitive
    600:    when computing interior eigenvalues in case the shift-and-invert spectral
    601:    transformation is too costly and a good preconditioner is available.

    603:    The implemented method is Jacobi-Davidson {cite:p}`Sle00`, which may
    604:    be preferred to Generalized Davidson in difficult problems.

    606:    The preconditioner is specified via the internal `ST` object and its
    607:    associated `KSP`.

    609:    Details of the implementation are described in {cite:p}`Rom14`.

    611:    Level: beginner

    613: .seealso: [](ch:eps), `EPS`, `EPSType`, `EPSSetType()`, `EPSGetST()`
    614: M*/
    615: SLEPC_EXTERN PetscErrorCode EPSCreate_JD(EPS eps)
    616: {
    617:   EPS_DAVIDSON   *data;

    619:   PetscFunctionBegin;
    620:   PetscCall(PetscNew(&data));
    621:   eps->data = (void*)data;

    623:   data->blocksize   = 1;
    624:   data->initialsize = 0;
    625:   data->minv        = 0;
    626:   data->plusk       = PETSC_DETERMINE;
    627:   data->ipB         = PETSC_TRUE;
    628:   data->fix         = 0.01;
    629:   data->krylovstart = PETSC_FALSE;
    630:   data->dynamic     = PETSC_FALSE;

    632:   eps->useds = PETSC_TRUE;
    633:   eps->categ = EPS_CATEGORY_PRECOND;

    635:   eps->ops->solve          = EPSSolve_XD;
    636:   eps->ops->setup          = EPSSetUp_JD;
    637:   eps->ops->setupsort      = EPSSetUpSort_Default;
    638:   eps->ops->setfromoptions = EPSSetFromOptions_JD;
    639:   eps->ops->destroy        = EPSDestroy_JD;
    640:   eps->ops->reset          = EPSReset_XD;
    641:   eps->ops->view           = EPSView_JD;
    642:   eps->ops->backtransform  = EPSBackTransform_Default;
    643:   eps->ops->computevectors = EPSComputeVectors_XD;
    644:   eps->ops->setdefaultst   = EPSSetDefaultST_JD;

    646:   PetscCall(PetscObjectComposeFunction((PetscObject)eps,"EPSJDSetKrylovStart_C",EPSXDSetKrylovStart_XD));
    647:   PetscCall(PetscObjectComposeFunction((PetscObject)eps,"EPSJDGetKrylovStart_C",EPSXDGetKrylovStart_XD));
    648:   PetscCall(PetscObjectComposeFunction((PetscObject)eps,"EPSJDSetBlockSize_C",EPSXDSetBlockSize_XD));
    649:   PetscCall(PetscObjectComposeFunction((PetscObject)eps,"EPSJDGetBlockSize_C",EPSXDGetBlockSize_XD));
    650:   PetscCall(PetscObjectComposeFunction((PetscObject)eps,"EPSJDSetRestart_C",EPSXDSetRestart_XD));
    651:   PetscCall(PetscObjectComposeFunction((PetscObject)eps,"EPSJDGetRestart_C",EPSXDGetRestart_XD));
    652:   PetscCall(PetscObjectComposeFunction((PetscObject)eps,"EPSJDSetInitialSize_C",EPSXDSetInitialSize_XD));
    653:   PetscCall(PetscObjectComposeFunction((PetscObject)eps,"EPSJDGetInitialSize_C",EPSXDGetInitialSize_XD));
    654:   PetscCall(PetscObjectComposeFunction((PetscObject)eps,"EPSJDSetFix_C",EPSJDSetFix_JD));
    655:   PetscCall(PetscObjectComposeFunction((PetscObject)eps,"EPSJDGetFix_C",EPSJDGetFix_JD));
    656:   PetscCall(PetscObjectComposeFunction((PetscObject)eps,"EPSJDSetConstCorrectionTol_C",EPSJDSetConstCorrectionTol_JD));
    657:   PetscCall(PetscObjectComposeFunction((PetscObject)eps,"EPSJDGetConstCorrectionTol_C",EPSJDGetConstCorrectionTol_JD));
    658:   PetscCall(PetscObjectComposeFunction((PetscObject)eps,"EPSJDSetBOrth_C",EPSXDSetBOrth_XD));
    659:   PetscCall(PetscObjectComposeFunction((PetscObject)eps,"EPSJDGetBOrth_C",EPSXDGetBOrth_XD));
    660:   PetscFunctionReturn(PETSC_SUCCESS);
    661: }