1: /*
2: - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
3: SLEPc - Scalable Library for Eigenvalue Problem Computations
4: Copyright (c) 2002-2019, 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: "gd"
13: Method: Generalized Davidson
15: Algorithm:
17: Generalized Davidson with various subspace extraction and
18: restart techniques.
20: References:
22: [1] E.R. Davidson, "Super-matrix methods", Comput. Phys. Commun.
23: 53(2):49-60, 1989.
25: [2] E. Romero and J.E. Roman, "A parallel implementation of
26: Davidson methods for large-scale eigenvalue problems in
27: SLEPc", ACM Trans. Math. Software 40(2), Article 13, 2014.
28: */
30: #include <slepc/private/epsimpl.h> /*I "slepceps.h" I*/
31: #include <../src/eps/impls/davidson/davidson.h>
33: PetscErrorCode EPSSetFromOptions_GD(PetscOptionItems *PetscOptionsObject,EPS eps) 34: {
36: PetscBool flg,flg2,op,orth;
37: PetscInt opi,opi0;
40: PetscOptionsHead(PetscOptionsObject,"EPS Generalized Davidson (GD) Options");
42: EPSGDGetKrylovStart(eps,&op);
43: PetscOptionsBool("-eps_gd_krylov_start","Start the search subspace with a Krylov basis","EPSGDSetKrylovStart",op,&op,&flg);
44: if (flg) { EPSGDSetKrylovStart(eps,op); }
46: EPSGDGetBOrth(eps,&orth);
47: PetscOptionsBool("-eps_gd_borth","Use B-orthogonalization in the search subspace","EPSGDSetBOrth",op,&op,&flg);
48: if (flg) { EPSGDSetBOrth(eps,op); }
50: EPSGDGetBlockSize(eps,&opi);
51: PetscOptionsInt("-eps_gd_blocksize","Number of vectors to add to the search subspace","EPSGDSetBlockSize",opi,&opi,&flg);
52: if (flg) { EPSGDSetBlockSize(eps,opi); }
54: EPSGDGetRestart(eps,&opi,&opi0);
55: PetscOptionsInt("-eps_gd_minv","Size of the search subspace after restarting","EPSGDSetRestart",opi,&opi,&flg);
56: PetscOptionsInt("-eps_gd_plusk","Number of eigenvectors saved from the previous iteration when restarting","EPSGDSetRestart",opi0,&opi0,&flg2);
57: if (flg || flg2) { EPSGDSetRestart(eps,opi,opi0); }
59: EPSGDGetInitialSize(eps,&opi);
60: PetscOptionsInt("-eps_gd_initial_size","Initial size of the search subspace","EPSGDSetInitialSize",opi,&opi,&flg);
61: if (flg) { EPSGDSetInitialSize(eps,opi); }
63: PetscOptionsBool("-eps_gd_double_expansion","Use the doble-expansion variant of GD","EPSGDSetDoubleExpansion",PETSC_FALSE,&op,&flg);
64: if (flg) { EPSGDSetDoubleExpansion(eps,op); }
66: PetscOptionsTail();
67: return(0);
68: }
70: PetscErrorCode EPSSetUp_GD(EPS eps) 71: {
73: PetscBool t;
74: KSP ksp;
77: /* Setup common for all davidson solvers */
78: EPSSetUp_XD(eps);
80: /* Check some constraints */
81: STGetKSP(eps->st,&ksp);
82: PetscObjectTypeCompare((PetscObject)ksp,KSPPREONLY,&t);
83: if (!t) SETERRQ(PetscObjectComm((PetscObject)eps),PETSC_ERR_SUP,"EPSGD only works with KSPPREONLY");
84: return(0);
85: }
87: PetscErrorCode EPSView_GD(EPS eps,PetscViewer viewer) 88: {
90: PetscBool isascii,opb;
91: PetscInt opi,opi0;
92: PetscBool borth;
93: EPS_DAVIDSON *data = (EPS_DAVIDSON*)eps->data;
96: PetscObjectTypeCompare((PetscObject)viewer,PETSCVIEWERASCII,&isascii);
97: if (isascii) {
98: if (data->doubleexp) {
99: PetscViewerASCIIPrintf(viewer," using double expansion variant (GD2)\n");
100: }
101: EPSXDGetBOrth_XD(eps,&borth);
102: if (borth) {
103: PetscViewerASCIIPrintf(viewer," search subspace is B-orthogonalized\n");
104: } else {
105: PetscViewerASCIIPrintf(viewer," search subspace is orthogonalized\n");
106: }
107: EPSXDGetBlockSize_XD(eps,&opi);
108: PetscViewerASCIIPrintf(viewer," block size=%D\n",opi);
109: EPSXDGetKrylovStart_XD(eps,&opb);
110: if (!opb) {
111: PetscViewerASCIIPrintf(viewer," type of the initial subspace: non-Krylov\n");
112: } else {
113: PetscViewerASCIIPrintf(viewer," type of the initial subspace: Krylov\n");
114: }
115: EPSXDGetRestart_XD(eps,&opi,&opi0);
116: PetscViewerASCIIPrintf(viewer," size of the subspace after restarting: %D\n",opi);
117: PetscViewerASCIIPrintf(viewer," number of vectors after restarting from the previous iteration: %D\n",opi0);
118: }
119: return(0);
120: }
122: PetscErrorCode EPSDestroy_GD(EPS eps)123: {
124: PetscErrorCode ierr;
127: PetscFree(eps->data);
128: PetscObjectComposeFunction((PetscObject)eps,"EPSGDSetKrylovStart_C",NULL);
129: PetscObjectComposeFunction((PetscObject)eps,"EPSGDGetKrylovStart_C",NULL);
130: PetscObjectComposeFunction((PetscObject)eps,"EPSGDSetBOrth_C",NULL);
131: PetscObjectComposeFunction((PetscObject)eps,"EPSGDGetBOrth_C",NULL);
132: PetscObjectComposeFunction((PetscObject)eps,"EPSGDSetBlockSize_C",NULL);
133: PetscObjectComposeFunction((PetscObject)eps,"EPSGDGetBlockSize_C",NULL);
134: PetscObjectComposeFunction((PetscObject)eps,"EPSGDSetRestart_C",NULL);
135: PetscObjectComposeFunction((PetscObject)eps,"EPSGDGetRestart_C",NULL);
136: PetscObjectComposeFunction((PetscObject)eps,"EPSGDSetInitialSize_C",NULL);
137: PetscObjectComposeFunction((PetscObject)eps,"EPSGDGetInitialSize_C",NULL);
138: PetscObjectComposeFunction((PetscObject)eps,"EPSGDSetDoubleExpansion_C",NULL);
139: PetscObjectComposeFunction((PetscObject)eps,"EPSGDGetDoubleExpansion_C",NULL);
140: return(0);
141: }
143: /*@
144: EPSGDSetKrylovStart - Activates or deactivates starting the searching
145: subspace with a Krylov basis.
147: Logically Collective on EPS149: Input Parameters:
150: + eps - the eigenproblem solver context
151: - krylovstart - boolean flag
153: Options Database Key:
154: . -eps_gd_krylov_start - Activates starting the searching subspace with a
155: Krylov basis
157: Level: advanced
159: .seealso: EPSGDGetKrylovStart()
160: @*/
161: PetscErrorCode EPSGDSetKrylovStart(EPS eps,PetscBool krylovstart)162: {
168: PetscTryMethod(eps,"EPSGDSetKrylovStart_C",(EPS,PetscBool),(eps,krylovstart));
169: return(0);
170: }
172: /*@
173: EPSGDGetKrylovStart - Returns a flag indicating if the search subspace is started with a
174: Krylov basis.
176: Not Collective
178: Input Parameter:
179: . eps - the eigenproblem solver context
181: Output Parameters:
182: . krylovstart - boolean flag indicating if the search subspace is started
183: with a Krylov basis
185: Level: advanced
187: .seealso: EPSGDGetKrylovStart()
188: @*/
189: PetscErrorCode EPSGDGetKrylovStart(EPS eps,PetscBool *krylovstart)190: {
196: PetscUseMethod(eps,"EPSGDGetKrylovStart_C",(EPS,PetscBool*),(eps,krylovstart));
197: return(0);
198: }
200: /*@
201: EPSGDSetBlockSize - Sets the number of vectors to be added to the searching space
202: in every iteration.
204: Logically Collective on EPS206: Input Parameters:
207: + eps - the eigenproblem solver context
208: - blocksize - number of vectors added to the search space in every iteration
210: Options Database Key:
211: . -eps_gd_blocksize - number of vectors added to the search space in every iteration
213: Level: advanced
215: .seealso: EPSGDSetKrylovStart()
216: @*/
217: PetscErrorCode EPSGDSetBlockSize(EPS eps,PetscInt blocksize)218: {
224: PetscTryMethod(eps,"EPSGDSetBlockSize_C",(EPS,PetscInt),(eps,blocksize));
225: return(0);
226: }
228: /*@
229: EPSGDGetBlockSize - Returns the number of vectors to be added to the searching space
230: in every iteration.
232: Not Collective
234: Input Parameter:
235: . eps - the eigenproblem solver context
237: Output Parameter:
238: . blocksize - number of vectors added to the search space in every iteration
240: Level: advanced
242: .seealso: EPSGDSetBlockSize()
243: @*/
244: PetscErrorCode EPSGDGetBlockSize(EPS eps,PetscInt *blocksize)245: {
251: PetscUseMethod(eps,"EPSGDGetBlockSize_C",(EPS,PetscInt*),(eps,blocksize));
252: return(0);
253: }
255: /*@
256: EPSGDSetRestart - Sets the number of vectors of the searching space after
257: restarting and the number of vectors saved from the previous iteration.
259: Logically Collective on EPS261: Input Parameters:
262: + eps - the eigenproblem solver context
263: . minv - number of vectors of the searching subspace after restarting
264: - plusk - number of vectors saved from the previous iteration
266: Options Database Keys:
267: + -eps_gd_minv - number of vectors of the searching subspace after restarting
268: - -eps_gd_plusk - number of vectors saved from the previous iteration
270: Level: advanced
272: .seealso: EPSGDSetRestart()
273: @*/
274: PetscErrorCode EPSGDSetRestart(EPS eps,PetscInt minv,PetscInt plusk)275: {
282: PetscTryMethod(eps,"EPSGDSetRestart_C",(EPS,PetscInt,PetscInt),(eps,minv,plusk));
283: return(0);
284: }
286: /*@
287: EPSGDGetRestart - Gets the number of vectors of the searching space after
288: restarting and the number of vectors saved from the previous iteration.
290: Not Collective
292: Input Parameter:
293: . eps - the eigenproblem solver context
295: Output Parameter:
296: + minv - number of vectors of the searching subspace after restarting
297: - plusk - number of vectors saved from the previous iteration
299: Level: advanced
301: .seealso: EPSGDSetRestart()
302: @*/
303: PetscErrorCode EPSGDGetRestart(EPS eps,PetscInt *minv,PetscInt *plusk)304: {
309: PetscUseMethod(eps,"EPSGDGetRestart_C",(EPS,PetscInt*,PetscInt*),(eps,minv,plusk));
310: return(0);
311: }
313: /*@
314: EPSGDSetInitialSize - Sets the initial size of the searching space.
316: Logically Collective on EPS318: Input Parameters:
319: + eps - the eigenproblem solver context
320: - initialsize - number of vectors of the initial searching subspace
322: Options Database Key:
323: . -eps_gd_initial_size - number of vectors of the initial searching subspace
325: Notes:
326: If EPSGDGetKrylovStart() is PETSC_FALSE and the user provides vectors with
327: EPSSetInitialSpace(), up to initialsize vectors will be used; and if the
328: provided vectors are not enough, the solver completes the subspace with
329: random vectors. In the case of EPSGDGetKrylovStart() being PETSC_TRUE, the solver
330: gets the first vector provided by the user or, if not available, a random vector,
331: and expands the Krylov basis up to initialsize vectors.
333: Level: advanced
335: .seealso: EPSGDGetInitialSize(), EPSGDGetKrylovStart()
336: @*/
337: PetscErrorCode EPSGDSetInitialSize(EPS eps,PetscInt initialsize)338: {
344: PetscTryMethod(eps,"EPSGDSetInitialSize_C",(EPS,PetscInt),(eps,initialsize));
345: return(0);
346: }
348: /*@
349: EPSGDGetInitialSize - Returns the initial size of the searching space.
351: Not Collective
353: Input Parameter:
354: . eps - the eigenproblem solver context
356: Output Parameter:
357: . initialsize - number of vectors of the initial searching subspace
359: Notes:
360: If EPSGDGetKrylovStart() is PETSC_FALSE and the user provides vectors with
361: EPSSetInitialSpace(), up to initialsize vectors will be used; and if the
362: provided vectors are not enough, the solver completes the subspace with
363: random vectors. In the case of EPSGDGetKrylovStart() being PETSC_TRUE, the solver
364: gets the first vector provided by the user or, if not available, a random vector,
365: and expands the Krylov basis up to initialsize vectors.
367: Level: advanced
369: .seealso: EPSGDSetInitialSize(), EPSGDGetKrylovStart()
370: @*/
371: PetscErrorCode EPSGDGetInitialSize(EPS eps,PetscInt *initialsize)372: {
378: PetscUseMethod(eps,"EPSGDGetInitialSize_C",(EPS,PetscInt*),(eps,initialsize));
379: return(0);
380: }
382: /*@
383: EPSGDSetBOrth - Selects the orthogonalization that will be used in the search
384: subspace in case of generalized Hermitian problems.
386: Logically Collective on EPS388: Input Parameters:
389: + eps - the eigenproblem solver context
390: - borth - whether to B-orthogonalize the search subspace
392: Options Database Key:
393: . -eps_gd_borth - Set the orthogonalization used in the search subspace
395: Level: advanced
397: .seealso: EPSGDGetBOrth()
398: @*/
399: PetscErrorCode EPSGDSetBOrth(EPS eps,PetscBool borth)400: {
406: PetscTryMethod(eps,"EPSGDSetBOrth_C",(EPS,PetscBool),(eps,borth));
407: return(0);
408: }
410: /*@
411: EPSGDGetBOrth - Returns the orthogonalization used in the search
412: subspace in case of generalized Hermitian problems.
414: Not Collective
416: Input Parameter:
417: . eps - the eigenproblem solver context
419: Output Parameters:
420: . borth - whether to B-orthogonalize the search subspace
422: Level: advanced
424: .seealso: EPSGDSetBOrth()
425: @*/
426: PetscErrorCode EPSGDGetBOrth(EPS eps,PetscBool *borth)427: {
433: PetscUseMethod(eps,"EPSGDGetBOrth_C",(EPS,PetscBool*),(eps,borth));
434: return(0);
435: }
437: static PetscErrorCode EPSGDSetDoubleExpansion_GD(EPS eps,PetscBool doubleexp)438: {
439: EPS_DAVIDSON *data = (EPS_DAVIDSON*)eps->data;
442: data->doubleexp = doubleexp;
443: return(0);
444: }
446: /*@
447: EPSGDSetDoubleExpansion - Activate a variant where the search subspace is
448: expanded with K*[A*x B*x] (double expansion) instead of the classic K*r,
449: where K is the preconditioner, x the selected approximate eigenvector and
450: r its associated residual vector.
452: Logically Collective on EPS454: Input Parameters:
455: + eps - the eigenproblem solver context
456: - doubleexp - the boolean flag
458: Options Database Keys:
459: . -eps_gd_double_expansion - activate the double-expansion variant of GD
461: Level: advanced
462: @*/
463: PetscErrorCode EPSGDSetDoubleExpansion(EPS eps,PetscBool doubleexp)464: {
470: PetscTryMethod(eps,"EPSGDSetDoubleExpansion_C",(EPS,PetscBool),(eps,doubleexp));
471: return(0);
472: }
474: static PetscErrorCode EPSGDGetDoubleExpansion_GD(EPS eps,PetscBool *doubleexp)475: {
476: EPS_DAVIDSON *data = (EPS_DAVIDSON*)eps->data;
479: *doubleexp = data->doubleexp;
480: return(0);
481: }
483: /*@
484: EPSGDGetDoubleExpansion - Gets a flag indicating whether the double
485: expansion variant has been activated or not.
487: Not Collective
489: Input Parameter:
490: . eps - the eigenproblem solver context
492: Output Parameter:
493: . doubleexp - the flag
495: Level: advanced
497: .seealso: EPSGDSetDoubleExpansion()
498: @*/
499: PetscErrorCode EPSGDGetDoubleExpansion(EPS eps,PetscBool *doubleexp)500: {
506: PetscUseMethod(eps,"EPSGDGetDoubleExpansion_C",(EPS,PetscBool*),(eps,doubleexp));
507: return(0);
508: }
510: SLEPC_EXTERN PetscErrorCode EPSCreate_GD(EPS eps)511: {
512: PetscErrorCode ierr;
513: EPS_DAVIDSON *data;
516: PetscNewLog(eps,&data);
517: eps->data = (void*)data;
519: data->blocksize = 1;
520: data->initialsize = 6;
521: data->minv = 6;
522: data->plusk = PETSC_DEFAULT;
523: data->ipB = PETSC_TRUE;
524: data->fix = 0.0;
525: data->krylovstart = PETSC_FALSE;
526: data->dynamic = PETSC_FALSE;
528: eps->useds = PETSC_TRUE;
529: eps->categ = EPS_CATEGORY_PRECOND;
531: eps->ops->solve = EPSSolve_XD;
532: eps->ops->setup = EPSSetUp_GD;
533: eps->ops->setfromoptions = EPSSetFromOptions_GD;
534: eps->ops->destroy = EPSDestroy_GD;
535: eps->ops->reset = EPSReset_XD;
536: eps->ops->view = EPSView_GD;
537: eps->ops->backtransform = EPSBackTransform_Default;
538: eps->ops->computevectors = EPSComputeVectors_XD;
539: eps->ops->setdefaultst = EPSSetDefaultST_Precond;
541: PetscObjectComposeFunction((PetscObject)eps,"EPSGDSetKrylovStart_C",EPSXDSetKrylovStart_XD);
542: PetscObjectComposeFunction((PetscObject)eps,"EPSGDGetKrylovStart_C",EPSXDGetKrylovStart_XD);
543: PetscObjectComposeFunction((PetscObject)eps,"EPSGDSetBOrth_C",EPSXDSetBOrth_XD);
544: PetscObjectComposeFunction((PetscObject)eps,"EPSGDGetBOrth_C",EPSXDGetBOrth_XD);
545: PetscObjectComposeFunction((PetscObject)eps,"EPSGDSetBlockSize_C",EPSXDSetBlockSize_XD);
546: PetscObjectComposeFunction((PetscObject)eps,"EPSGDGetBlockSize_C",EPSXDGetBlockSize_XD);
547: PetscObjectComposeFunction((PetscObject)eps,"EPSGDSetRestart_C",EPSXDSetRestart_XD);
548: PetscObjectComposeFunction((PetscObject)eps,"EPSGDGetRestart_C",EPSXDGetRestart_XD);
549: PetscObjectComposeFunction((PetscObject)eps,"EPSGDSetInitialSize_C",EPSXDSetInitialSize_XD);
550: PetscObjectComposeFunction((PetscObject)eps,"EPSGDGetInitialSize_C",EPSXDGetInitialSize_XD);
551: PetscObjectComposeFunction((PetscObject)eps,"EPSGDSetDoubleExpansion_C",EPSGDSetDoubleExpansion_GD);
552: PetscObjectComposeFunction((PetscObject)eps,"EPSGDGetDoubleExpansion_C",EPSGDGetDoubleExpansion_GD);
553: return(0);
554: }