1: /*
2: - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
3: SLEPc - Scalable Library for Eigenvalue Problem Computations
4: Copyright (c) 2002-2017, 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> /*I "slepceps.h" I*/
32: #include <../src/eps/impls/davidson/davidson.h>
34: PetscErrorCode EPSSetFromOptions_JD(PetscOptionItems *PetscOptionsObject,EPS eps) 35: {
37: PetscBool flg,flg2,op,orth;
38: PetscInt opi,opi0;
39: PetscReal opf;
42: PetscOptionsHead(PetscOptionsObject,"EPS Jacobi-Davidson (JD) Options");
44: EPSJDGetKrylovStart(eps,&op);
45: PetscOptionsBool("-eps_jd_krylov_start","Start the search subspace with a Krylov basis","EPSJDSetKrylovStart",op,&op,&flg);
46: if (flg) { EPSJDSetKrylovStart(eps,op); }
48: EPSJDGetBOrth(eps,&orth);
49: PetscOptionsBool("-eps_jd_borth","Use B-orthogonalization in the search subspace","EPSJDSetBOrth",op,&op,&flg);
50: if (flg) { EPSJDSetBOrth(eps,op); }
52: EPSJDGetBlockSize(eps,&opi);
53: PetscOptionsInt("-eps_jd_blocksize","Number of vectors to add to the search subspace","EPSJDSetBlockSize",opi,&opi,&flg);
54: if (flg) { EPSJDSetBlockSize(eps,opi); }
56: EPSJDGetRestart(eps,&opi,&opi0);
57: PetscOptionsInt("-eps_jd_minv","Size of the search subspace after restarting","EPSJDSetRestart",opi,&opi,&flg);
58: PetscOptionsInt("-eps_jd_plusk","Number of eigenvectors saved from the previous iteration when restarting","EPSJDSetRestart",opi0,&opi0,&flg2);
59: if (flg || flg2) { EPSJDSetRestart(eps,opi,opi0); }
61: EPSJDGetInitialSize(eps,&opi);
62: PetscOptionsInt("-eps_jd_initial_size","Initial size of the search subspace","EPSJDSetInitialSize",opi,&opi,&flg);
63: if (flg) { EPSJDSetInitialSize(eps,opi); }
65: EPSJDGetFix(eps,&opf);
66: PetscOptionsReal("-eps_jd_fix","Tolerance for changing the target in the correction equation","EPSJDSetFix",opf,&opf,&flg);
67: if (flg) { EPSJDSetFix(eps,opf); }
69: EPSJDGetConstCorrectionTol(eps,&op);
70: PetscOptionsBool("-eps_jd_const_correction_tol","Disable the dynamic stopping criterion when solving the correction equation","EPSJDSetConstCorrectionTol",op,&op,&flg);
71: if (flg) { EPSJDSetConstCorrectionTol(eps,op); }
73: PetscOptionsTail();
74: return(0);
75: }
77: PetscErrorCode EPSSetDefaultST_JD(EPS eps) 78: {
80: KSP ksp;
83: if (!((PetscObject)eps->st)->type_name) {
84: STSetType(eps->st,STPRECOND);
85: STPrecondSetKSPHasMat(eps->st,PETSC_TRUE);
86: }
87: STGetKSP(eps->st,&ksp);
88: if (!((PetscObject)ksp)->type_name) {
89: KSPSetType(ksp,KSPBCGSL);
90: KSPSetTolerances(ksp,1e-4,PETSC_DEFAULT,PETSC_DEFAULT,90);
91: }
92: return(0);
93: }
95: PetscErrorCode EPSSetUp_JD(EPS eps) 96: {
98: PetscBool t;
99: KSP ksp;
102: /* Setup common for all davidson solvers */
103: EPSSetUp_XD(eps);
105: /* Check some constraints */
106: STGetKSP(eps->st,&ksp);
107: PetscObjectTypeCompare((PetscObject)ksp,KSPPREONLY,&t);
108: if (t) SETERRQ(PetscObjectComm((PetscObject)eps),PETSC_ERR_SUP,"EPSJD does not work with KSPPREONLY");
109: return(0);
110: }
112: PetscErrorCode EPSView_JD(EPS eps,PetscViewer viewer)113: {
115: PetscBool isascii,opb;
116: PetscInt opi,opi0;
117: PetscBool borth;
120: PetscObjectTypeCompare((PetscObject)viewer,PETSCVIEWERASCII,&isascii);
121: if (isascii) {
122: EPSXDGetBOrth_XD(eps,&borth);
123: if (borth) {
124: PetscViewerASCIIPrintf(viewer," search subspace is B-orthogonalized\n");
125: } else {
126: PetscViewerASCIIPrintf(viewer," search subspace is orthogonalized\n");
127: }
128: EPSXDGetBlockSize_XD(eps,&opi);
129: PetscViewerASCIIPrintf(viewer," block size=%D\n",opi);
130: EPSXDGetKrylovStart_XD(eps,&opb);
131: if (!opb) {
132: PetscViewerASCIIPrintf(viewer," type of the initial subspace: non-Krylov\n");
133: } else {
134: PetscViewerASCIIPrintf(viewer," type of the initial subspace: Krylov\n");
135: }
136: EPSXDGetRestart_XD(eps,&opi,&opi0);
137: PetscViewerASCIIPrintf(viewer," size of the subspace after restarting: %D\n",opi);
138: PetscViewerASCIIPrintf(viewer," number of vectors after restarting from the previous iteration: %D\n",opi0);
139: }
140: return(0);
141: }
143: PetscErrorCode EPSDestroy_JD(EPS eps)144: {
145: PetscErrorCode ierr;
148: PetscFree(eps->data);
149: PetscObjectComposeFunction((PetscObject)eps,"EPSJDSetKrylovStart_C",NULL);
150: PetscObjectComposeFunction((PetscObject)eps,"EPSJDGetKrylovStart_C",NULL);
151: PetscObjectComposeFunction((PetscObject)eps,"EPSJDSetBlockSize_C",NULL);
152: PetscObjectComposeFunction((PetscObject)eps,"EPSJDGetBlockSize_C",NULL);
153: PetscObjectComposeFunction((PetscObject)eps,"EPSJDSetRestart_C",NULL);
154: PetscObjectComposeFunction((PetscObject)eps,"EPSJDGetRestart_C",NULL);
155: PetscObjectComposeFunction((PetscObject)eps,"EPSJDSetInitialSize_C",NULL);
156: PetscObjectComposeFunction((PetscObject)eps,"EPSJDGetInitialSize_C",NULL);
157: PetscObjectComposeFunction((PetscObject)eps,"EPSJDSetFix_C",NULL);
158: PetscObjectComposeFunction((PetscObject)eps,"EPSJDGetFix_C",NULL);
159: PetscObjectComposeFunction((PetscObject)eps,"EPSJDSetConstCorrectionTol_C",NULL);
160: PetscObjectComposeFunction((PetscObject)eps,"EPSJDGetConstCorrectionTol_C",NULL);
161: PetscObjectComposeFunction((PetscObject)eps,"EPSJDSetBOrth_C",NULL);
162: PetscObjectComposeFunction((PetscObject)eps,"EPSJDGetBOrth_C",NULL);
163: return(0);
164: }
166: /*@
167: EPSJDSetKrylovStart - Activates or deactivates starting the searching
168: subspace with a Krylov basis.
170: Logically Collective on EPS172: Input Parameters:
173: + eps - the eigenproblem solver context
174: - krylovstart - boolean flag
176: Options Database Key:
177: . -eps_jd_krylov_start - Activates starting the searching subspace with a
178: Krylov basis
180: Level: advanced
182: .seealso: EPSJDGetKrylovStart()
183: @*/
184: PetscErrorCode EPSJDSetKrylovStart(EPS eps,PetscBool krylovstart)185: {
191: PetscTryMethod(eps,"EPSJDSetKrylovStart_C",(EPS,PetscBool),(eps,krylovstart));
192: return(0);
193: }
195: /*@
196: EPSJDGetKrylovStart - Returns a flag indicating if the searching subspace is started with a
197: Krylov basis.
199: Not Collective
201: Input Parameter:
202: . eps - the eigenproblem solver context
204: Output Parameters:
205: . krylovstart - boolean flag indicating if the searching subspace is started
206: with a Krylov basis
208: Level: advanced
210: .seealso: EPSJDGetKrylovStart()
211: @*/
212: PetscErrorCode EPSJDGetKrylovStart(EPS eps,PetscBool *krylovstart)213: {
219: PetscUseMethod(eps,"EPSJDGetKrylovStart_C",(EPS,PetscBool*),(eps,krylovstart));
220: return(0);
221: }
223: /*@
224: EPSJDSetBlockSize - Sets the number of vectors to be added to the searching space
225: in every iteration.
227: Logically Collective on EPS229: Input Parameters:
230: + eps - the eigenproblem solver context
231: - blocksize - number of vectors added to the search space in every iteration
233: Options Database Key:
234: . -eps_jd_blocksize - number of vectors added to the searching space every iteration
236: Level: advanced
238: .seealso: EPSJDSetKrylovStart()
239: @*/
240: PetscErrorCode EPSJDSetBlockSize(EPS eps,PetscInt blocksize)241: {
247: PetscTryMethod(eps,"EPSJDSetBlockSize_C",(EPS,PetscInt),(eps,blocksize));
248: return(0);
249: }
251: /*@
252: EPSJDGetBlockSize - Returns the number of vectors to be added to the searching space
253: in every iteration.
255: Not Collective
257: Input Parameter:
258: . eps - the eigenproblem solver context
260: Output Parameter:
261: . blocksize - number of vectors added to the search space in every iteration
263: Level: advanced
265: .seealso: EPSJDSetBlockSize()
266: @*/
267: PetscErrorCode EPSJDGetBlockSize(EPS eps,PetscInt *blocksize)268: {
274: PetscUseMethod(eps,"EPSJDGetBlockSize_C",(EPS,PetscInt*),(eps,blocksize));
275: return(0);
276: }
278: /*@
279: EPSJDSetRestart - Sets the number of vectors of the searching space after
280: restarting and the number of vectors saved from the previous iteration.
282: Logically Collective on EPS284: Input Parameters:
285: + eps - the eigenproblem solver context
286: . minv - number of vectors of the searching subspace after restarting
287: - plusk - number of vectors saved from the previous iteration
289: Options Database Keys:
290: + -eps_jd_minv - number of vectors of the searching subspace after restarting
291: - -eps_jd_plusk - number of vectors saved from the previous iteration
293: Level: advanced
295: .seealso: EPSJDGetRestart()
296: @*/
297: PetscErrorCode EPSJDSetRestart(EPS eps,PetscInt minv,PetscInt plusk)298: {
305: PetscTryMethod(eps,"EPSJDSetRestart_C",(EPS,PetscInt,PetscInt),(eps,minv,plusk));
306: return(0);
307: }
309: /*@
310: EPSJDGetRestart - Gets the number of vectors of the searching space after
311: restarting and the number of vectors saved from the previous iteration.
313: Not Collective
315: Input Parameter:
316: . eps - the eigenproblem solver context
318: Output Parameter:
319: + minv - number of vectors of the searching subspace after restarting
320: - plusk - number of vectors saved from the previous iteration
322: Level: advanced
324: .seealso: EPSJDSetRestart()
325: @*/
326: PetscErrorCode EPSJDGetRestart(EPS eps,PetscInt *minv,PetscInt *plusk)327: {
332: PetscUseMethod(eps,"EPSJDGetRestart_C",(EPS,PetscInt*,PetscInt*),(eps,minv,plusk));
333: return(0);
334: }
336: /*@
337: EPSJDSetInitialSize - Sets the initial size of the searching space.
339: Logically Collective on EPS341: Input Parameters:
342: + eps - the eigenproblem solver context
343: - initialsize - number of vectors of the initial searching subspace
345: Options Database Key:
346: . -eps_jd_initial_size - number of vectors of the initial searching subspace
348: Notes:
349: If EPSJDGetKrylovStart() is PETSC_FALSE and the user provides vectors with
350: EPSSetInitialSpace(), up to initialsize vectors will be used; and if the
351: provided vectors are not enough, the solver completes the subspace with
352: random vectors. In the case of EPSJDGetKrylovStart() being PETSC_TRUE, the solver
353: gets the first vector provided by the user or, if not available, a random vector,
354: and expands the Krylov basis up to initialsize vectors.
356: Level: advanced
358: .seealso: EPSJDGetInitialSize(), EPSJDGetKrylovStart()
359: @*/
360: PetscErrorCode EPSJDSetInitialSize(EPS eps,PetscInt initialsize)361: {
367: PetscTryMethod(eps,"EPSJDSetInitialSize_C",(EPS,PetscInt),(eps,initialsize));
368: return(0);
369: }
371: /*@
372: EPSJDGetInitialSize - Returns the initial size of the searching space.
374: Not Collective
376: Input Parameter:
377: . eps - the eigenproblem solver context
379: Output Parameter:
380: . initialsize - number of vectors of the initial searching subspace
382: Notes:
383: If EPSJDGetKrylovStart() is PETSC_FALSE and the user provides vectors with
384: EPSSetInitialSpace(), up to initialsize vectors will be used; and if the
385: provided vectors are not enough, the solver completes the subspace with
386: random vectors. In the case of EPSJDGetKrylovStart() being PETSC_TRUE, the solver
387: gets the first vector provided by the user or, if not available, a random vector,
388: and expands the Krylov basis up to initialsize vectors.
390: Level: advanced
392: .seealso: EPSJDSetInitialSize(), EPSJDGetKrylovStart()
393: @*/
394: PetscErrorCode EPSJDGetInitialSize(EPS eps,PetscInt *initialsize)395: {
401: PetscUseMethod(eps,"EPSJDGetInitialSize_C",(EPS,PetscInt*),(eps,initialsize));
402: return(0);
403: }
405: PetscErrorCode EPSJDSetFix_JD(EPS eps,PetscReal fix)406: {
407: EPS_DAVIDSON *data = (EPS_DAVIDSON*)eps->data;
410: if (fix == PETSC_DEFAULT || fix == PETSC_DECIDE) fix = 0.01;
411: if (fix < 0.0) SETERRQ(PetscObjectComm((PetscObject)eps),PETSC_ERR_ARG_OUTOFRANGE,"Invalid fix value");
412: data->fix = fix;
413: return(0);
414: }
416: /*@
417: EPSJDSetFix - Sets the threshold for changing the target in the correction
418: equation.
420: Logically Collective on EPS422: Input Parameters:
423: + eps - the eigenproblem solver context
424: - fix - threshold for changing the target
426: Options Database Key:
427: . -eps_jd_fix - the fix value
429: Note:
430: The target in the correction equation is fixed at the first iterations.
431: When the norm of the residual vector is lower than the fix value,
432: the target is set to the corresponding eigenvalue.
434: Level: advanced
436: .seealso: EPSJDGetFix()
437: @*/
438: PetscErrorCode EPSJDSetFix(EPS eps,PetscReal fix)439: {
445: PetscTryMethod(eps,"EPSJDSetFix_C",(EPS,PetscReal),(eps,fix));
446: return(0);
447: }
449: PetscErrorCode EPSJDGetFix_JD(EPS eps,PetscReal *fix)450: {
451: EPS_DAVIDSON *data = (EPS_DAVIDSON*)eps->data;
454: *fix = data->fix;
455: return(0);
456: }
458: /*@
459: EPSJDGetFix - Returns the threshold for changing the target in the correction
460: equation.
462: Not Collective
464: Input Parameter:
465: . eps - the eigenproblem solver context
467: Output Parameter:
468: . fix - threshold for changing the target
470: Note:
471: The target in the correction equation is fixed at the first iterations.
472: When the norm of the residual vector is lower than the fix value,
473: the target is set to the corresponding eigenvalue.
475: Level: advanced
477: .seealso: EPSJDSetFix()
478: @*/
479: PetscErrorCode EPSJDGetFix(EPS eps,PetscReal *fix)480: {
486: PetscUseMethod(eps,"EPSJDGetFix_C",(EPS,PetscReal*),(eps,fix));
487: return(0);
488: }
490: PetscErrorCode EPSJDSetConstCorrectionTol_JD(EPS eps,PetscBool constant)491: {
492: EPS_DAVIDSON *data = (EPS_DAVIDSON*)eps->data;
495: data->dynamic = PetscNot(constant);
496: return(0);
497: }
499: /*@
500: EPSJDSetConstCorrectionTol - If true, deactivates the dynamic stopping criterion
501: (also called Newton) that sets the KSP relative tolerance
502: to 0.5**i, where i is the number of EPS iterations from the last converged value.
504: Logically Collective on EPS506: Input Parameters:
507: + eps - the eigenproblem solver context
508: - constant - if false, the KSP relative tolerance is set to 0.5**i.
510: Options Database Key:
511: . -eps_jd_const_correction_tol - Deactivates the dynamic stopping criterion.
513: Level: advanced
515: .seealso: EPSJDGetConstCorrectionTol()
516: @*/
517: PetscErrorCode EPSJDSetConstCorrectionTol(EPS eps,PetscBool constant)518: {
524: PetscTryMethod(eps,"EPSJDSetConstCorrectionTol_C",(EPS,PetscBool),(eps,constant));
525: return(0);
526: }
528: PetscErrorCode EPSJDGetConstCorrectionTol_JD(EPS eps,PetscBool *constant)529: {
530: EPS_DAVIDSON *data = (EPS_DAVIDSON*)eps->data;
533: *constant = PetscNot(data->dynamic);
534: return(0);
535: }
537: /*@
538: EPSJDGetConstCorrectionTol - Returns a flag indicating if the dynamic stopping is being used for
539: solving the correction equation. If the flag is false the KSP relative tolerance is set
540: to 0.5**i, where i is the number of EPS iterations from the last converged value.
542: Not Collective
544: Input Parameter:
545: . eps - the eigenproblem solver context
547: Output Parameters:
548: . constant - boolean flag indicating if the dynamic stopping criterion is not being used.
550: Level: advanced
552: .seealso: EPSJDGetConstCorrectionTol()
553: @*/
554: PetscErrorCode EPSJDGetConstCorrectionTol(EPS eps,PetscBool *constant)555: {
561: PetscUseMethod(eps,"EPSJDGetConstCorrectionTol_C",(EPS,PetscBool*),(eps,constant));
562: return(0);
563: }
565: /*@
566: EPSJDSetBOrth - Selects the orthogonalization that will be used in the search
567: subspace in case of generalized Hermitian problems.
569: Logically Collective on EPS571: Input Parameters:
572: + eps - the eigenproblem solver context
573: - borth - whether to B-orthogonalize the search subspace
575: Options Database Key:
576: . -eps_jd_borth - Set the orthogonalization used in the search subspace
578: Level: advanced
580: .seealso: EPSJDGetBOrth()
581: @*/
582: PetscErrorCode EPSJDSetBOrth(EPS eps,PetscBool borth)583: {
589: PetscTryMethod(eps,"EPSJDSetBOrth_C",(EPS,PetscBool),(eps,borth));
590: return(0);
591: }
593: /*@
594: EPSJDGetBOrth - Returns the orthogonalization used in the search
595: subspace in case of generalized Hermitian problems.
597: Not Collective
599: Input Parameter:
600: . eps - the eigenproblem solver context
602: Output Parameters:
603: . borth - whether to B-orthogonalize the search subspace
605: Level: advanced
607: .seealso: EPSJDSetBOrth()
608: @*/
609: PetscErrorCode EPSJDGetBOrth(EPS eps,PetscBool *borth)610: {
616: PetscUseMethod(eps,"EPSJDGetBOrth_C",(EPS,PetscBool*),(eps,borth));
617: return(0);
618: }
620: PETSC_EXTERN PetscErrorCode EPSCreate_JD(EPS eps)621: {
623: EPS_DAVIDSON *data;
626: PetscNewLog(eps,&data);
627: eps->data = (void*)data;
629: data->blocksize = 1;
630: data->initialsize = 6;
631: data->minv = 6;
632: data->plusk = PETSC_DEFAULT;
633: data->ipB = PETSC_TRUE;
634: data->fix = 0.01;
635: data->krylovstart = PETSC_FALSE;
636: data->dynamic = PETSC_FALSE;
638: eps->useds = PETSC_TRUE;
639: eps->categ = EPS_CATEGORY_PRECOND;
641: eps->ops->solve = EPSSolve_XD;
642: eps->ops->setup = EPSSetUp_JD;
643: eps->ops->setfromoptions = EPSSetFromOptions_JD;
644: eps->ops->destroy = EPSDestroy_JD;
645: eps->ops->reset = EPSReset_XD;
646: eps->ops->view = EPSView_JD;
647: eps->ops->backtransform = EPSBackTransform_Default;
648: eps->ops->computevectors = EPSComputeVectors_XD;
649: eps->ops->setdefaultst = EPSSetDefaultST_JD;
651: PetscObjectComposeFunction((PetscObject)eps,"EPSJDSetKrylovStart_C",EPSXDSetKrylovStart_XD);
652: PetscObjectComposeFunction((PetscObject)eps,"EPSJDGetKrylovStart_C",EPSXDGetKrylovStart_XD);
653: PetscObjectComposeFunction((PetscObject)eps,"EPSJDSetBlockSize_C",EPSXDSetBlockSize_XD);
654: PetscObjectComposeFunction((PetscObject)eps,"EPSJDGetBlockSize_C",EPSXDGetBlockSize_XD);
655: PetscObjectComposeFunction((PetscObject)eps,"EPSJDSetRestart_C",EPSXDSetRestart_XD);
656: PetscObjectComposeFunction((PetscObject)eps,"EPSJDGetRestart_C",EPSXDGetRestart_XD);
657: PetscObjectComposeFunction((PetscObject)eps,"EPSJDSetInitialSize_C",EPSXDSetInitialSize_XD);
658: PetscObjectComposeFunction((PetscObject)eps,"EPSJDGetInitialSize_C",EPSXDGetInitialSize_XD);
659: PetscObjectComposeFunction((PetscObject)eps,"EPSJDSetFix_C",EPSJDSetFix_JD);
660: PetscObjectComposeFunction((PetscObject)eps,"EPSJDGetFix_C",EPSJDGetFix_JD);
661: PetscObjectComposeFunction((PetscObject)eps,"EPSJDSetConstCorrectionTol_C",EPSJDSetConstCorrectionTol_JD);
662: PetscObjectComposeFunction((PetscObject)eps,"EPSJDGetConstCorrectionTol_C",EPSJDGetConstCorrectionTol_JD);
663: PetscObjectComposeFunction((PetscObject)eps,"EPSJDSetBOrth_C",EPSXDSetBOrth_XD);
664: PetscObjectComposeFunction((PetscObject)eps,"EPSJDGetBOrth_C",EPSXDGetBOrth_XD);
665: return(0);
666: }