1: /*
3: SLEPc eigensolver: "gd"
5: Method: Generalized Davidson
7: Algorithm:
9: Generalized Davidson with various subspace extraction and
10: restart techniques.
12: References:
14: [1] E.R. Davidson, "Super-matrix methods", Comput. Phys. Commun.
15: 53(2):49-60, 1989.
17: [2] E. Romero and J.E. Roman, "A parallel implementation of
18: Davidson methods for large-scale eigenvalue problems in
19: SLEPc", ACM Trans. Math. Software 40(2), Article 13, 2014.
21: - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
22: SLEPc - Scalable Library for Eigenvalue Problem Computations
23: Copyright (c) 2002-2016, Universitat Politecnica de Valencia, Spain
25: This file is part of SLEPc.
27: SLEPc is free software: you can redistribute it and/or modify it under the
28: terms of version 3 of the GNU Lesser General Public License as published by
29: the Free Software Foundation.
31: SLEPc is distributed in the hope that it will be useful, but WITHOUT ANY
32: WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
33: FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for
34: more details.
36: You should have received a copy of the GNU Lesser General Public License
37: along with SLEPc. If not, see <http://www.gnu.org/licenses/>.
38: - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
39: */
41: #include <slepc/private/epsimpl.h> /*I "slepceps.h" I*/
42: #include <../src/eps/impls/davidson/davidson.h>
46: PetscErrorCode EPSSetFromOptions_GD(PetscOptionItems *PetscOptionsObject,EPS eps) 47: {
49: PetscBool flg,op;
50: PetscInt opi,opi0;
51: KSP ksp;
52: PetscBool orth;
53: const char *orth_list[2] = {"I","B"};
56: PetscOptionsHead(PetscOptionsObject,"EPS Generalized Davidson (GD) Options");
58: EPSGDGetKrylovStart(eps,&op);
59: PetscOptionsBool("-eps_gd_krylov_start","Start the searching subspace with a krylov basis","EPSGDSetKrylovStart",op,&op,&flg);
60: if (flg) { EPSGDSetKrylovStart(eps,op); }
62: EPSGDGetBOrth(eps,&orth);
63: PetscOptionsEList("-eps_gd_borth","orthogonalization used in the search subspace","EPSGDSetBOrth",orth_list,2,orth_list[orth?1:0],&opi,&flg);
64: if (flg) { EPSGDSetBOrth(eps,opi==1?PETSC_TRUE:PETSC_FALSE); }
66: EPSGDGetBlockSize(eps,&opi);
67: PetscOptionsInt("-eps_gd_blocksize","Number vectors add to the searching subspace","EPSGDSetBlockSize",opi,&opi,&flg);
68: if (flg) { EPSGDSetBlockSize(eps,opi); }
70: EPSGDGetRestart(eps,&opi,&opi0);
71: PetscOptionsInt("-eps_gd_minv","Set the size of the searching subspace after restarting","EPSGDSetRestart",opi,&opi,&flg);
72: if (flg) { EPSGDSetRestart(eps,opi,opi0); }
74: PetscOptionsInt("-eps_gd_plusk","Set the number of saved eigenvectors from the previous iteration when restarting","EPSGDSetRestart",opi0,&opi0,&flg);
75: if (flg) { EPSGDSetRestart(eps,opi,opi0); }
77: EPSGDGetInitialSize(eps,&opi);
78: PetscOptionsInt("-eps_gd_initial_size","Set the initial size of the searching subspace","EPSGDSetInitialSize",opi,&opi,&flg);
79: if (flg) { EPSGDSetInitialSize(eps,opi); }
81: EPSGDGetWindowSizes(eps,&opi,&opi0);
82: PetscOptionsInt("-eps_gd_pwindow","(Experimental!) Set the number of converged vectors in the projector","EPSGDSetWindowSizes",opi,&opi,&flg);
83: if (flg) { EPSGDSetWindowSizes(eps,opi,opi0); }
85: PetscOptionsInt("-eps_gd_qwindow","(Experimental!) Set the number of converged vectors in the projected problem","EPSGDSetWindowSizes",opi0,&opi0,&flg);
86: if (flg) { EPSGDSetWindowSizes(eps,opi,opi0); }
88: PetscOptionsBool("-eps_gd_double_expansion","use the doble-expansion variant of GD","EPSGDSetDoubleExpansion",PETSC_FALSE,&op,&flg);
89: if (flg) { EPSGDSetDoubleExpansion(eps,op); }
91: /* Set STPrecond as the default ST */
92: if (!((PetscObject)eps->st)->type_name) {
93: STSetType(eps->st,STPRECOND);
94: }
95: STPrecondSetKSPHasMat(eps->st,PETSC_FALSE);
97: /* Set the default options of the KSP */
98: STGetKSP(eps->st,&ksp);
99: if (!((PetscObject)ksp)->type_name) {
100: KSPSetType(ksp,KSPPREONLY);
101: }
102: PetscOptionsTail();
103: return(0);
104: }
108: PetscErrorCode EPSSetUp_GD(EPS eps)109: {
111: PetscBool t;
112: KSP ksp;
115: /* Set KSPPREONLY as default */
116: STGetKSP(eps->st,&ksp);
117: if (!((PetscObject)ksp)->type_name) {
118: KSPSetType(ksp,KSPPREONLY);
119: }
121: /* Setup common for all davidson solvers */
122: EPSSetUp_XD(eps);
124: /* Check some constraints */
125: PetscObjectTypeCompare((PetscObject)ksp,KSPPREONLY,&t);
126: if (!t) SETERRQ(PetscObjectComm((PetscObject)eps),PETSC_ERR_SUP,"EPSGD only works with KSPPREONLY");
127: return(0);
128: }
132: PetscErrorCode EPSView_GD(EPS eps,PetscViewer viewer)133: {
135: PetscBool isascii,opb;
136: PetscInt opi,opi0;
137: PetscBool borth;
138: EPS_DAVIDSON *data = (EPS_DAVIDSON*)eps->data;
141: PetscObjectTypeCompare((PetscObject)viewer,PETSCVIEWERASCII,&isascii);
142: if (isascii) {
143: if (data->doubleexp) {
144: PetscViewerASCIIPrintf(viewer," GD: using double expansion variant (GD2)\n");
145: }
146: EPSXDGetBOrth_XD(eps,&borth);
147: if (borth) {
148: PetscViewerASCIIPrintf(viewer," GD: search subspace is B-orthogonalized\n");
149: } else {
150: PetscViewerASCIIPrintf(viewer," GD: search subspace is orthogonalized\n");
151: }
152: EPSXDGetBlockSize_XD(eps,&opi);
153: PetscViewerASCIIPrintf(viewer," GD: block size=%D\n",opi);
154: EPSXDGetKrylovStart_XD(eps,&opb);
155: if (!opb) {
156: PetscViewerASCIIPrintf(viewer," GD: type of the initial subspace: non-Krylov\n");
157: } else {
158: PetscViewerASCIIPrintf(viewer," GD: type of the initial subspace: Krylov\n");
159: }
160: EPSXDGetRestart_XD(eps,&opi,&opi0);
161: PetscViewerASCIIPrintf(viewer," GD: size of the subspace after restarting: %D\n",opi);
162: PetscViewerASCIIPrintf(viewer," GD: number of vectors after restarting from the previous iteration: %D\n",opi0);
163: }
164: return(0);
165: }
169: PetscErrorCode EPSDestroy_GD(EPS eps)170: {
171: PetscErrorCode ierr;
174: PetscFree(eps->data);
175: PetscObjectComposeFunction((PetscObject)eps,"EPSGDSetKrylovStart_C",NULL);
176: PetscObjectComposeFunction((PetscObject)eps,"EPSGDGetKrylovStart_C",NULL);
177: PetscObjectComposeFunction((PetscObject)eps,"EPSGDSetBOrth_C",NULL);
178: PetscObjectComposeFunction((PetscObject)eps,"EPSGDGetBOrth_C",NULL);
179: PetscObjectComposeFunction((PetscObject)eps,"EPSGDSetBlockSize_C",NULL);
180: PetscObjectComposeFunction((PetscObject)eps,"EPSGDGetBlockSize_C",NULL);
181: PetscObjectComposeFunction((PetscObject)eps,"EPSGDSetRestart_C",NULL);
182: PetscObjectComposeFunction((PetscObject)eps,"EPSGDGetRestart_C",NULL);
183: PetscObjectComposeFunction((PetscObject)eps,"EPSGDSetInitialSize_C",NULL);
184: PetscObjectComposeFunction((PetscObject)eps,"EPSGDGetInitialSize_C",NULL);
185: PetscObjectComposeFunction((PetscObject)eps,"EPSGDSetWindowSizes_C",NULL);
186: PetscObjectComposeFunction((PetscObject)eps,"EPSGDGetWindowSizes_C",NULL);
187: PetscObjectComposeFunction((PetscObject)eps,"EPSGDSetDoubleExpansion_C",NULL);
188: PetscObjectComposeFunction((PetscObject)eps,"EPSGDGetDoubleExpansion_C",NULL);
189: return(0);
190: }
194: /*@
195: EPSGDSetKrylovStart - Activates or deactivates starting the searching
196: subspace with a Krylov basis.
198: Logically Collective on EPS200: Input Parameters:
201: + eps - the eigenproblem solver context
202: - krylovstart - boolean flag
204: Options Database Key:
205: . -eps_gd_krylov_start - Activates starting the searching subspace with a
206: Krylov basis
208: Level: advanced
210: .seealso: EPSGDGetKrylovStart()
211: @*/
212: PetscErrorCode EPSGDSetKrylovStart(EPS eps,PetscBool krylovstart)213: {
219: PetscTryMethod(eps,"EPSGDSetKrylovStart_C",(EPS,PetscBool),(eps,krylovstart));
220: return(0);
221: }
225: /*@
226: EPSGDGetKrylovStart - Returns a flag indicating if the search subspace is started with a
227: Krylov basis.
229: Not Collective
231: Input Parameter:
232: . eps - the eigenproblem solver context
234: Output Parameters:
235: . krylovstart - boolean flag indicating if the search subspace is started
236: with a Krylov basis
238: Level: advanced
240: .seealso: EPSGDGetKrylovStart()
241: @*/
242: PetscErrorCode EPSGDGetKrylovStart(EPS eps,PetscBool *krylovstart)243: {
249: PetscUseMethod(eps,"EPSGDGetKrylovStart_C",(EPS,PetscBool*),(eps,krylovstart));
250: return(0);
251: }
255: /*@
256: EPSGDSetBlockSize - Sets the number of vectors to be added to the searching space
257: in every iteration.
259: Logically Collective on EPS261: Input Parameters:
262: + eps - the eigenproblem solver context
263: - blocksize - number of vectors added to the search space in every iteration
265: Options Database Key:
266: . -eps_gd_blocksize - number of vectors added to the search space in every iteration
268: Level: advanced
270: .seealso: EPSGDSetKrylovStart()
271: @*/
272: PetscErrorCode EPSGDSetBlockSize(EPS eps,PetscInt blocksize)273: {
279: PetscTryMethod(eps,"EPSGDSetBlockSize_C",(EPS,PetscInt),(eps,blocksize));
280: return(0);
281: }
285: /*@
286: EPSGDGetBlockSize - Returns the number of vectors to be added to the searching space
287: in every iteration.
289: Not Collective
291: Input Parameter:
292: . eps - the eigenproblem solver context
294: Output Parameter:
295: . blocksize - number of vectors added to the search space in every iteration
297: Level: advanced
299: .seealso: EPSGDSetBlockSize()
300: @*/
301: PetscErrorCode EPSGDGetBlockSize(EPS eps,PetscInt *blocksize)302: {
308: PetscUseMethod(eps,"EPSGDGetBlockSize_C",(EPS,PetscInt*),(eps,blocksize));
309: return(0);
310: }
314: /*@
315: EPSGDGetRestart - Gets the number of vectors of the searching space after
316: restarting and the number of vectors saved from the previous iteration.
318: Not Collective
320: Input Parameter:
321: . eps - the eigenproblem solver context
323: Output Parameter:
324: + minv - number of vectors of the searching subspace after restarting
325: - plusk - number of vectors saved from the previous iteration
327: Level: advanced
329: .seealso: EPSGDSetRestart()
330: @*/
331: PetscErrorCode EPSGDGetRestart(EPS eps,PetscInt *minv,PetscInt *plusk)332: {
337: PetscUseMethod(eps,"EPSGDGetRestart_C",(EPS,PetscInt*,PetscInt*),(eps,minv,plusk));
338: return(0);
339: }
343: /*@
344: EPSGDSetRestart - Sets the number of vectors of the searching space after
345: restarting and the number of vectors saved from the previous iteration.
347: Logically Collective on EPS349: Input Parameters:
350: + eps - the eigenproblem solver context
351: . minv - number of vectors of the searching subspace after restarting
352: - plusk - number of vectors saved from the previous iteration
354: Options Database Keys:
355: + -eps_gd_minv - number of vectors of the searching subspace after restarting
356: - -eps_gd_plusk - number of vectors saved from the previous iteration
358: Level: advanced
360: .seealso: EPSGDSetRestart()
361: @*/
362: PetscErrorCode EPSGDSetRestart(EPS eps,PetscInt minv,PetscInt plusk)363: {
370: PetscTryMethod(eps,"EPSGDSetRestart_C",(EPS,PetscInt,PetscInt),(eps,minv,plusk));
371: return(0);
372: }
376: /*@
377: EPSGDGetInitialSize - Returns the initial size of the searching space.
379: Not Collective
381: Input Parameter:
382: . eps - the eigenproblem solver context
384: Output Parameter:
385: . initialsize - number of vectors of the initial searching subspace
387: Notes:
388: If EPSGDGetKrylovStart() is PETSC_FALSE and the user provides vectors with
389: EPSSetInitialSpace(), up to initialsize vectors will be used; and if the
390: provided vectors are not enough, the solver completes the subspace with
391: random vectors. In the case of EPSGDGetKrylovStart() being PETSC_TRUE, the solver
392: gets the first vector provided by the user or, if not available, a random vector,
393: and expands the Krylov basis up to initialsize vectors.
395: Level: advanced
397: .seealso: EPSGDSetInitialSize(), EPSGDGetKrylovStart()
398: @*/
399: PetscErrorCode EPSGDGetInitialSize(EPS eps,PetscInt *initialsize)400: {
406: PetscUseMethod(eps,"EPSGDGetInitialSize_C",(EPS,PetscInt*),(eps,initialsize));
407: return(0);
408: }
412: /*@
413: EPSGDSetInitialSize - Sets the initial size of the searching space.
415: Logically Collective on EPS417: Input Parameters:
418: + eps - the eigenproblem solver context
419: - initialsize - number of vectors of the initial searching subspace
421: Options Database Key:
422: . -eps_gd_initial_size - number of vectors of the initial searching subspace
424: Notes:
425: If EPSGDGetKrylovStart() is PETSC_FALSE and the user provides vectors with
426: EPSSetInitialSpace(), up to initialsize vectors will be used; and if the
427: provided vectors are not enough, the solver completes the subspace with
428: random vectors. In the case of EPSGDGetKrylovStart() being PETSC_TRUE, the solver
429: gets the first vector provided by the user or, if not available, a random vector,
430: and expands the Krylov basis up to initialsize vectors.
432: Level: advanced
434: .seealso: EPSGDGetInitialSize(), EPSGDGetKrylovStart()
435: @*/
436: PetscErrorCode EPSGDSetInitialSize(EPS eps,PetscInt initialsize)437: {
443: PetscTryMethod(eps,"EPSGDSetInitialSize_C",(EPS,PetscInt),(eps,initialsize));
444: return(0);
445: }
449: /*@
450: EPSGDSetBOrth - Selects the orthogonalization that will be used in the search
451: subspace in case of generalized Hermitian problems.
453: Logically Collective on EPS455: Input Parameters:
456: + eps - the eigenproblem solver context
457: - borth - whether to B-orthogonalize the search subspace
459: Options Database Key:
460: . -eps_gd_borth - Set the orthogonalization used in the search subspace
462: Level: advanced
464: .seealso: EPSGDGetBOrth()
465: @*/
466: PetscErrorCode EPSGDSetBOrth(EPS eps,PetscBool borth)467: {
473: PetscTryMethod(eps,"EPSGDSetBOrth_C",(EPS,PetscBool),(eps,borth));
474: return(0);
475: }
479: /*@
480: EPSGDGetBOrth - Returns the orthogonalization used in the search
481: subspace in case of generalized Hermitian problems.
483: Not Collective
485: Input Parameter:
486: . eps - the eigenproblem solver context
488: Output Parameters:
489: . borth - whether to B-orthogonalize the search subspace
491: Level: advanced
493: .seealso: EPSGDSetBOrth()
494: @*/
495: PetscErrorCode EPSGDGetBOrth(EPS eps,PetscBool *borth)496: {
502: PetscUseMethod(eps,"EPSGDGetBOrth_C",(EPS,PetscBool*),(eps,borth));
503: return(0);
504: }
508: /*@
509: EPSGDGetWindowSizes - Gets the number of converged vectors in the projected
510: problem (or Rayleigh quotient) and in the projector employed in the correction
511: equation.
513: Not Collective
515: Input Parameter:
516: . eps - the eigenproblem solver context
518: Output Parameter:
519: + pwindow - number of converged vectors in the projector
520: - qwindow - number of converged vectors in the projected problem
522: Level: advanced
524: .seealso: EPSGDSetWindowSizes()
525: @*/
526: PetscErrorCode EPSGDGetWindowSizes(EPS eps,PetscInt *pwindow,PetscInt *qwindow)527: {
532: PetscUseMethod(eps,"EPSGDGetWindowSizes_C",(EPS,PetscInt*,PetscInt*),(eps,pwindow,qwindow));
533: return(0);
534: }
538: /*@
539: EPSGDSetWindowSizes - Sets the number of converged vectors in the projected
540: problem (or Rayleigh quotient) and in the projector employed in the correction
541: equation.
543: Logically Collective on EPS545: Input Parameters:
546: + eps - the eigenproblem solver context
547: . pwindow - number of converged vectors in the projector
548: - qwindow - number of converged vectors in the projected problem
550: Options Database Keys:
551: + -eps_gd_pwindow - set the number of converged vectors in the projector
552: - -eps_gd_qwindow - set the number of converged vectors in the projected problem
554: Level: advanced
556: .seealso: EPSGDGetWindowSizes()
557: @*/
558: PetscErrorCode EPSGDSetWindowSizes(EPS eps,PetscInt pwindow,PetscInt qwindow)559: {
566: PetscTryMethod(eps,"EPSGDSetWindowSizes_C",(EPS,PetscInt,PetscInt),(eps,pwindow,qwindow));
567: return(0);
568: }
572: static PetscErrorCode EPSGDGetDoubleExpansion_GD(EPS eps,PetscBool *doubleexp)573: {
574: EPS_DAVIDSON *data = (EPS_DAVIDSON*)eps->data;
577: *doubleexp = data->doubleexp;
578: return(0);
579: }
583: /*@
584: EPSGDGetDoubleExpansion - Gets a flag indicating whether the double
585: expansion variant has been activated or not.
587: Not Collective
589: Input Parameter:
590: . eps - the eigenproblem solver context
592: Output Parameter:
593: . doubleexp - the flag
595: Level: advanced
597: .seealso: EPSGDSetDoubleExpansion()
598: @*/
599: PetscErrorCode EPSGDGetDoubleExpansion(EPS eps,PetscBool *doubleexp)600: {
606: PetscUseMethod(eps,"EPSGDGetDoubleExpansion_C",(EPS,PetscBool*),(eps,doubleexp));
607: return(0);
608: }
612: static PetscErrorCode EPSGDSetDoubleExpansion_GD(EPS eps,PetscBool doubleexp)613: {
614: EPS_DAVIDSON *data = (EPS_DAVIDSON*)eps->data;
617: data->doubleexp = doubleexp;
618: return(0);
619: }
623: /*@
624: EPSGDSetDoubleExpansion - Activate a variant where the search subspace is
625: expanded with K*[A*x B*x] (double expansion) instead of the classic K*r,
626: where K is the preconditioner, x the selected approximate eigenvector and
627: r its associated residual vector.
629: Logically Collective on EPS631: Input Parameters:
632: + eps - the eigenproblem solver context
633: - doubleexp - the boolean flag
635: Options Database Keys:
636: . -eps_gd_double_expansion - activate the double-expansion variant of GD
638: Level: advanced
639: @*/
640: PetscErrorCode EPSGDSetDoubleExpansion(EPS eps,PetscBool doubleexp)641: {
647: PetscTryMethod(eps,"EPSGDSetDoubleExpansion_C",(EPS,PetscBool),(eps,doubleexp));
648: return(0);
649: }
653: PETSC_EXTERN PetscErrorCode EPSCreate_GD(EPS eps)654: {
655: PetscErrorCode ierr;
656: EPS_DAVIDSON *data;
659: PetscNewLog(eps,&data);
660: eps->data = (void*)data;
662: data->blocksize = 1;
663: data->initialsize = 6;
664: data->minv = 6;
665: data->plusk = 0;
666: data->ipB = PETSC_TRUE;
667: data->fix = 0.0;
668: data->krylovstart = PETSC_FALSE;
669: data->dynamic = PETSC_FALSE;
670: data->cX_in_proj = 0;
671: data->cX_in_impr = 0;
673: eps->ops->solve = EPSSolve_XD;
674: eps->ops->setup = EPSSetUp_XD;
675: eps->ops->reset = EPSReset_XD;
676: eps->ops->backtransform = EPSBackTransform_Default;
677: eps->ops->computevectors = EPSComputeVectors_XD;
678: eps->ops->view = EPSView_GD;
679: eps->ops->setfromoptions = EPSSetFromOptions_GD;
680: eps->ops->setup = EPSSetUp_GD;
681: eps->ops->destroy = EPSDestroy_GD;
683: PetscObjectComposeFunction((PetscObject)eps,"EPSGDSetKrylovStart_C",EPSXDSetKrylovStart_XD);
684: PetscObjectComposeFunction((PetscObject)eps,"EPSGDGetKrylovStart_C",EPSXDGetKrylovStart_XD);
685: PetscObjectComposeFunction((PetscObject)eps,"EPSGDSetBOrth_C",EPSXDSetBOrth_XD);
686: PetscObjectComposeFunction((PetscObject)eps,"EPSGDGetBOrth_C",EPSXDGetBOrth_XD);
687: PetscObjectComposeFunction((PetscObject)eps,"EPSGDSetBlockSize_C",EPSXDSetBlockSize_XD);
688: PetscObjectComposeFunction((PetscObject)eps,"EPSGDGetBlockSize_C",EPSXDGetBlockSize_XD);
689: PetscObjectComposeFunction((PetscObject)eps,"EPSGDSetRestart_C",EPSXDSetRestart_XD);
690: PetscObjectComposeFunction((PetscObject)eps,"EPSGDGetRestart_C",EPSXDGetRestart_XD);
691: PetscObjectComposeFunction((PetscObject)eps,"EPSGDSetInitialSize_C",EPSXDSetInitialSize_XD);
692: PetscObjectComposeFunction((PetscObject)eps,"EPSGDGetInitialSize_C",EPSXDGetInitialSize_XD);
693: PetscObjectComposeFunction((PetscObject)eps,"EPSGDSetWindowSizes_C",EPSXDSetWindowSizes_XD);
694: PetscObjectComposeFunction((PetscObject)eps,"EPSGDGetWindowSizes_C",EPSXDGetWindowSizes_XD);
695: PetscObjectComposeFunction((PetscObject)eps,"EPSGDSetDoubleExpansion_C",EPSGDSetDoubleExpansion_GD);
696: PetscObjectComposeFunction((PetscObject)eps,"EPSGDGetDoubleExpansion_C",EPSGDGetDoubleExpansion_GD);
697: return(0);
698: }