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-2015, 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(PetscOptions *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 EPSDestroy_GD(EPS eps)133: {
134: PetscErrorCode ierr;
137: PetscFree(eps->data);
138: PetscObjectComposeFunction((PetscObject)eps,"EPSGDSetKrylovStart_C",NULL);
139: PetscObjectComposeFunction((PetscObject)eps,"EPSGDGetKrylovStart_C",NULL);
140: PetscObjectComposeFunction((PetscObject)eps,"EPSGDSetBOrth_C",NULL);
141: PetscObjectComposeFunction((PetscObject)eps,"EPSGDGetBOrth_C",NULL);
142: PetscObjectComposeFunction((PetscObject)eps,"EPSGDSetBlockSize_C",NULL);
143: PetscObjectComposeFunction((PetscObject)eps,"EPSGDGetBlockSize_C",NULL);
144: PetscObjectComposeFunction((PetscObject)eps,"EPSGDSetRestart_C",NULL);
145: PetscObjectComposeFunction((PetscObject)eps,"EPSGDGetRestart_C",NULL);
146: PetscObjectComposeFunction((PetscObject)eps,"EPSGDSetInitialSize_C",NULL);
147: PetscObjectComposeFunction((PetscObject)eps,"EPSGDGetInitialSize_C",NULL);
148: PetscObjectComposeFunction((PetscObject)eps,"EPSGDSetWindowSizes_C",NULL);
149: PetscObjectComposeFunction((PetscObject)eps,"EPSGDGetWindowSizes_C",NULL);
150: PetscObjectComposeFunction((PetscObject)eps,"EPSGDSetDoubleExpansion_C",NULL);
151: PetscObjectComposeFunction((PetscObject)eps,"EPSGDGetDoubleExpansion_C",NULL);
152: return(0);
153: }
157: /*@
158: EPSGDSetKrylovStart - Activates or deactivates starting the searching
159: subspace with a Krylov basis.
161: Logically Collective on EPS163: Input Parameters:
164: + eps - the eigenproblem solver context
165: - krylovstart - boolean flag
167: Options Database Key:
168: . -eps_gd_krylov_start - Activates starting the searching subspace with a
169: Krylov basis
171: Level: advanced
173: .seealso: EPSGDGetKrylovStart()
174: @*/
175: PetscErrorCode EPSGDSetKrylovStart(EPS eps,PetscBool krylovstart)176: {
182: PetscTryMethod(eps,"EPSGDSetKrylovStart_C",(EPS,PetscBool),(eps,krylovstart));
183: return(0);
184: }
188: /*@
189: EPSGDGetKrylovStart - Returns a flag indicating if the search subspace is started with a
190: Krylov basis.
192: Not Collective
194: Input Parameter:
195: . eps - the eigenproblem solver context
197: Output Parameters:
198: . krylovstart - boolean flag indicating if the search subspace is started
199: with a Krylov basis
201: Level: advanced
203: .seealso: EPSGDGetKrylovStart()
204: @*/
205: PetscErrorCode EPSGDGetKrylovStart(EPS eps,PetscBool *krylovstart)206: {
212: PetscTryMethod(eps,"EPSGDGetKrylovStart_C",(EPS,PetscBool*),(eps,krylovstart));
213: return(0);
214: }
218: /*@
219: EPSGDSetBlockSize - Sets the number of vectors to be added to the searching space
220: in every iteration.
222: Logically Collective on EPS224: Input Parameters:
225: + eps - the eigenproblem solver context
226: - blocksize - number of vectors added to the search space in every iteration
228: Options Database Key:
229: . -eps_gd_blocksize - number of vectors added to the search space in every iteration
231: Level: advanced
233: .seealso: EPSGDSetKrylovStart()
234: @*/
235: PetscErrorCode EPSGDSetBlockSize(EPS eps,PetscInt blocksize)236: {
242: PetscTryMethod(eps,"EPSGDSetBlockSize_C",(EPS,PetscInt),(eps,blocksize));
243: return(0);
244: }
248: /*@
249: EPSGDGetBlockSize - Returns the number of vectors to be added to the searching space
250: in every iteration.
252: Not Collective
254: Input Parameter:
255: . eps - the eigenproblem solver context
257: Output Parameter:
258: . blocksize - number of vectors added to the search space in every iteration
260: Level: advanced
262: .seealso: EPSGDSetBlockSize()
263: @*/
264: PetscErrorCode EPSGDGetBlockSize(EPS eps,PetscInt *blocksize)265: {
271: PetscTryMethod(eps,"EPSGDGetBlockSize_C",(EPS,PetscInt*),(eps,blocksize));
272: return(0);
273: }
277: /*@
278: EPSGDGetRestart - Gets the number of vectors of the searching space after
279: restarting and the number of vectors saved from the previous iteration.
281: Not Collective
283: Input Parameter:
284: . eps - the eigenproblem solver context
286: Output Parameter:
287: + minv - number of vectors of the searching subspace after restarting
288: - plusk - number of vectors saved from the previous iteration
290: Level: advanced
292: .seealso: EPSGDSetRestart()
293: @*/
294: PetscErrorCode EPSGDGetRestart(EPS eps,PetscInt *minv,PetscInt *plusk)295: {
300: PetscTryMethod(eps,"EPSGDGetRestart_C",(EPS,PetscInt*,PetscInt*),(eps,minv,plusk));
301: return(0);
302: }
306: /*@
307: EPSGDSetRestart - Sets the number of vectors of the searching space after
308: restarting and the number of vectors saved from the previous iteration.
310: Logically Collective on EPS312: Input Parameters:
313: + eps - the eigenproblem solver context
314: . minv - number of vectors of the searching subspace after restarting
315: - plusk - number of vectors saved from the previous iteration
317: Options Database Keys:
318: + -eps_gd_minv - number of vectors of the searching subspace after restarting
319: - -eps_gd_plusk - number of vectors saved from the previous iteration
321: Level: advanced
323: .seealso: EPSGDSetRestart()
324: @*/
325: PetscErrorCode EPSGDSetRestart(EPS eps,PetscInt minv,PetscInt plusk)326: {
333: PetscTryMethod(eps,"EPSGDSetRestart_C",(EPS,PetscInt,PetscInt),(eps,minv,plusk));
334: return(0);
335: }
339: /*@
340: EPSGDGetInitialSize - Returns the initial size of the searching space.
342: Not Collective
344: Input Parameter:
345: . eps - the eigenproblem solver context
347: Output Parameter:
348: . initialsize - number of vectors of the initial searching subspace
350: Notes:
351: If EPSGDGetKrylovStart() is PETSC_FALSE and the user provides vectors with
352: EPSSetInitialSpace(), up to initialsize vectors will be used; and if the
353: provided vectors are not enough, the solver completes the subspace with
354: random vectors. In the case of EPSGDGetKrylovStart() being PETSC_TRUE, the solver
355: gets the first vector provided by the user or, if not available, a random vector,
356: and expands the Krylov basis up to initialsize vectors.
358: Level: advanced
360: .seealso: EPSGDSetInitialSize(), EPSGDGetKrylovStart()
361: @*/
362: PetscErrorCode EPSGDGetInitialSize(EPS eps,PetscInt *initialsize)363: {
369: PetscTryMethod(eps,"EPSGDGetInitialSize_C",(EPS,PetscInt*),(eps,initialsize));
370: return(0);
371: }
375: /*@
376: EPSGDSetInitialSize - Sets the initial size of the searching space.
378: Logically Collective on EPS380: Input Parameters:
381: + eps - the eigenproblem solver context
382: - initialsize - number of vectors of the initial searching subspace
384: Options Database Key:
385: . -eps_gd_initial_size - 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: EPSGDGetInitialSize(), EPSGDGetKrylovStart()
398: @*/
399: PetscErrorCode EPSGDSetInitialSize(EPS eps,PetscInt initialsize)400: {
406: PetscTryMethod(eps,"EPSGDSetInitialSize_C",(EPS,PetscInt),(eps,initialsize));
407: return(0);
408: }
412: /*@
413: EPSGDSetBOrth - Selects the orthogonalization that will be used in the search
414: subspace in case of generalized Hermitian problems.
416: Logically Collective on EPS418: Input Parameters:
419: + eps - the eigenproblem solver context
420: - borth - whether to B-orthogonalize the search subspace
422: Options Database Key:
423: . -eps_gd_borth - Set the orthogonalization used in the search subspace
425: Level: advanced
427: .seealso: EPSGDGetBOrth()
428: @*/
429: PetscErrorCode EPSGDSetBOrth(EPS eps,PetscBool borth)430: {
436: PetscTryMethod(eps,"EPSGDSetBOrth_C",(EPS,PetscBool),(eps,borth));
437: return(0);
438: }
442: /*@
443: EPSGDGetBOrth - Returns the orthogonalization used in the search
444: subspace in case of generalized Hermitian problems.
446: Not Collective
448: Input Parameter:
449: . eps - the eigenproblem solver context
451: Output Parameters:
452: . borth - whether to B-orthogonalize the search subspace
454: Level: advanced
456: .seealso: EPSGDSetBOrth()
457: @*/
458: PetscErrorCode EPSGDGetBOrth(EPS eps,PetscBool *borth)459: {
465: PetscTryMethod(eps,"EPSGDGetBOrth_C",(EPS,PetscBool*),(eps,borth));
466: return(0);
467: }
471: /*@
472: EPSGDGetWindowSizes - Gets the number of converged vectors in the projected
473: problem (or Rayleigh quotient) and in the projector employed in the correction
474: equation.
476: Not Collective
478: Input Parameter:
479: . eps - the eigenproblem solver context
481: Output Parameter:
482: + pwindow - number of converged vectors in the projector
483: - qwindow - number of converged vectors in the projected problem
485: Level: advanced
487: .seealso: EPSGDSetWindowSizes()
488: @*/
489: PetscErrorCode EPSGDGetWindowSizes(EPS eps,PetscInt *pwindow,PetscInt *qwindow)490: {
495: PetscTryMethod(eps,"EPSGDGetWindowSizes_C",(EPS,PetscInt*,PetscInt*),(eps,pwindow,qwindow));
496: return(0);
497: }
501: /*@
502: EPSGDSetWindowSizes - Sets the number of converged vectors in the projected
503: problem (or Rayleigh quotient) and in the projector employed in the correction
504: equation.
506: Logically Collective on EPS508: Input Parameters:
509: + eps - the eigenproblem solver context
510: . pwindow - number of converged vectors in the projector
511: - qwindow - number of converged vectors in the projected problem
513: Options Database Keys:
514: + -eps_gd_pwindow - set the number of converged vectors in the projector
515: - -eps_gd_qwindow - set the number of converged vectors in the projected problem
517: Level: advanced
519: .seealso: EPSGDGetWindowSizes()
520: @*/
521: PetscErrorCode EPSGDSetWindowSizes(EPS eps,PetscInt pwindow,PetscInt qwindow)522: {
529: PetscTryMethod(eps,"EPSGDSetWindowSizes_C",(EPS,PetscInt,PetscInt),(eps,pwindow,qwindow));
530: return(0);
531: }
535: static PetscErrorCode EPSGDSetDoubleExpansion_GD(EPS eps,PetscBool use_gd2)536: {
540: EPSXDSetMethod(eps,use_gd2?DVD_METH_GD2:DVD_METH_GD);
541: return(0);
542: }
546: static PetscErrorCode EPSGDGetDoubleExpansion_GD(EPS eps,PetscBool *flg)547: {
548: Method_t meth;
552: EPSXDGetMethod_XD(eps,&meth);
553: if (meth==DVD_METH_GD2) *flg = PETSC_TRUE;
554: else *flg = PETSC_FALSE;
555: return(0);
556: }
560: /*@
561: EPSGDGetDoubleExpansion - Gets a flag indicating whether the double
562: expansion variant has been activated or not.
564: Not Collective
566: Input Parameter:
567: . eps - the eigenproblem solver context
569: Output Parameter:
570: . flg - the flag
572: Level: advanced
574: .seealso: EPSGDSetDoubleExpansion()
575: @*/
576: PetscErrorCode EPSGDGetDoubleExpansion(EPS eps,PetscBool *flg)577: {
583: PetscTryMethod(eps,"EPSGDGetDoubleExpansion_C",(EPS,PetscBool*),(eps,flg));
584: return(0);
585: }
589: /*@
590: EPSGDSetDoubleExpansion - Activate a variant where the search subspace is
591: expanded with K*[A*x B*x] (double expansion) instead of the classic K*r,
592: where K is the preconditioner, x the selected approximate eigenvector and
593: r its associated residual vector.
595: Logically Collective on EPS597: Input Parameters:
598: + eps - the eigenproblem solver context
599: - use_gd2 - the boolean flag
601: Options Database Keys:
602: . -eps_gd_double_expansion - activate the double-expansion variant of GD
604: Level: advanced
605: @*/
606: PetscErrorCode EPSGDSetDoubleExpansion(EPS eps,PetscBool use_gd2)607: {
613: PetscTryMethod(eps,"EPSGDSetDoubleExpansion_C",(EPS,PetscBool),(eps,use_gd2));
614: return(0);
615: }
619: PETSC_EXTERN PetscErrorCode EPSCreate_GD(EPS eps)620: {
621: PetscErrorCode ierr;
624: /* Load the Davidson solver */
625: EPSCreate_XD(eps);
626: EPSJDSetFix_JD(eps,0.0);
627: EPSXDSetMethod(eps,DVD_METH_GD);
629: /* Overload the GD properties */
630: eps->ops->setfromoptions = EPSSetFromOptions_GD;
631: eps->ops->setup = EPSSetUp_GD;
632: eps->ops->destroy = EPSDestroy_GD;
634: PetscObjectComposeFunction((PetscObject)eps,"EPSGDSetKrylovStart_C",EPSXDSetKrylovStart_XD);
635: PetscObjectComposeFunction((PetscObject)eps,"EPSGDGetKrylovStart_C",EPSXDGetKrylovStart_XD);
636: PetscObjectComposeFunction((PetscObject)eps,"EPSGDSetBOrth_C",EPSXDSetBOrth_XD);
637: PetscObjectComposeFunction((PetscObject)eps,"EPSGDGetBOrth_C",EPSXDGetBOrth_XD);
638: PetscObjectComposeFunction((PetscObject)eps,"EPSGDSetBlockSize_C",EPSXDSetBlockSize_XD);
639: PetscObjectComposeFunction((PetscObject)eps,"EPSGDGetBlockSize_C",EPSXDGetBlockSize_XD);
640: PetscObjectComposeFunction((PetscObject)eps,"EPSGDSetRestart_C",EPSXDSetRestart_XD);
641: PetscObjectComposeFunction((PetscObject)eps,"EPSGDGetRestart_C",EPSXDGetRestart_XD);
642: PetscObjectComposeFunction((PetscObject)eps,"EPSGDSetInitialSize_C",EPSXDSetInitialSize_XD);
643: PetscObjectComposeFunction((PetscObject)eps,"EPSGDGetInitialSize_C",EPSXDGetInitialSize_XD);
644: PetscObjectComposeFunction((PetscObject)eps,"EPSGDSetWindowSizes_C",EPSXDSetWindowSizes_XD);
645: PetscObjectComposeFunction((PetscObject)eps,"EPSGDGetWindowSizes_C",EPSXDGetWindowSizes_XD);
646: PetscObjectComposeFunction((PetscObject)eps,"EPSGDSetDoubleExpansion_C",EPSGDSetDoubleExpansion_GD);
647: PetscObjectComposeFunction((PetscObject)eps,"EPSGDGetDoubleExpansion_C",EPSGDGetDoubleExpansion_GD);
648: return(0);
649: }