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: }