Actual source code: gd.c

  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", submitted, 2013.

 21:    Last update: Jul 2012

 23:    - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
 24:    SLEPc - Scalable Library for Eigenvalue Problem Computations
 25:    Copyright (c) 2002-2013, Universitat Politecnica de Valencia, Spain

 27:    This file is part of SLEPc.

 29:    SLEPc is free software: you can redistribute it and/or modify it under  the
 30:    terms of version 3 of the GNU Lesser General Public License as published by
 31:    the Free Software Foundation.

 33:    SLEPc  is  distributed in the hope that it will be useful, but WITHOUT  ANY
 34:    WARRANTY;  without even the implied warranty of MERCHANTABILITY or  FITNESS
 35:    FOR  A  PARTICULAR PURPOSE. See the GNU Lesser General Public  License  for
 36:    more details.

 38:    You  should have received a copy of the GNU Lesser General  Public  License
 39:    along with SLEPc. If not, see <http://www.gnu.org/licenses/>.
 40:    - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
 41: */

 43: #include <slepc-private/epsimpl.h>                /*I "slepceps.h" I*/
 44: #include <../src/eps/impls/davidson/common/davidson.h>

 48: PetscErrorCode EPSSetFromOptions_GD(EPS eps)
 49: {
 51:   PetscBool      flg,op;
 52:   PetscInt       opi,opi0;
 53:   KSP            ksp;
 54:   EPSOrthType    orth;
 55:   const char     *orth_list[3] = {"I","B","B_opt"};

 58:   PetscOptionsHead("EPS Generalized Davidson (GD) Options");

 60:   EPSGDGetKrylovStart(eps,&op);
 61:   PetscOptionsBool("-eps_gd_krylov_start","Start the searching subspace with a krylov basis","EPSGDSetKrylovStart",op,&op,&flg);
 62:   if (flg) { EPSGDSetKrylovStart(eps,op); }

 64:   EPSGDGetBOrth(eps,&orth);
 65:   PetscOptionsEList("-eps_gd_borth","orthogonalization used in the search subspace","EPSGDSetBOrth",orth_list,3,orth_list[orth-1],&opi,&flg);
 66:   if (flg) { EPSGDSetBOrth(eps,(EPSOrthType)(opi+1)); }

 68:   EPSGDGetBlockSize(eps,&opi);
 69:   PetscOptionsInt("-eps_gd_blocksize","Number vectors add to the searching subspace","EPSGDSetBlockSize",opi,&opi,&flg);
 70:   if (flg) { EPSGDSetBlockSize(eps,opi); }

 72:   EPSGDGetRestart(eps,&opi,&opi0);
 73:   PetscOptionsInt("-eps_gd_minv","Set the size of the searching subspace after restarting","EPSGDSetRestart",opi,&opi,&flg);
 74:   if (flg) { EPSGDSetRestart(eps,opi,opi0); }

 76:   PetscOptionsInt("-eps_gd_plusk","Set the number of saved eigenvectors from the previous iteration when restarting","EPSGDSetRestart",opi0,&opi0,&flg);
 77:   if (flg) { EPSGDSetRestart(eps,opi,opi0); }

 79:   EPSGDGetInitialSize(eps,&opi);
 80:   PetscOptionsInt("-eps_gd_initial_size","Set the initial size of the searching subspace","EPSGDSetInitialSize",opi,&opi,&flg);
 81:   if (flg) { EPSGDSetInitialSize(eps,opi); }

 83:   EPSGDGetWindowSizes(eps,&opi,&opi0);
 84:   PetscOptionsInt("-eps_gd_pwindow","(Experimental!) Set the number of converged vectors in the projector","EPSGDSetWindowSizes",opi,&opi,&flg);
 85:   if (flg) { EPSGDSetWindowSizes(eps,opi,opi0); }

 87:   PetscOptionsInt("-eps_gd_qwindow","(Experimental!) Set the number of converged vectors in the projected problem","EPSGDSetWindowSizes",opi0,&opi0,&flg);
 88:   if (flg) { EPSGDSetWindowSizes(eps,opi,opi0); }

 90:   PetscOptionsBool("-eps_gd_double_expansion","use the doble-expansion variant of GD","EPSGDSetDoubleExpansion",PETSC_FALSE,&op,&flg);
 91:   if (flg) { EPSGDSetDoubleExpansion(eps,op); }

 93:   /* Set STPrecond as the default ST */
 94:   if (!((PetscObject)eps->st)->type_name) {
 95:     STSetType(eps->st,STPRECOND);
 96:   }
 97:   STPrecondSetKSPHasMat(eps->st,PETSC_FALSE);

 99:   /* Set the default options of the KSP */
100:   STGetKSP(eps->st,&ksp);
101:   if (!((PetscObject)ksp)->type_name) {
102:     KSPSetType(ksp,KSPPREONLY);
103:   }
104:   PetscOptionsTail();
105:   return(0);
106: }

110: PetscErrorCode EPSSetUp_GD(EPS eps)
111: {
113:   PetscBool      t;
114:   KSP            ksp;

117:   /* Set KSPPREONLY as default */
118:   STGetKSP(eps->st,&ksp);
119:   if (!((PetscObject)ksp)->type_name) {
120:     KSPSetType(ksp,KSPPREONLY);
121:   }

123:   /* Setup common for all davidson solvers */
124:   EPSSetUp_XD(eps);

126:   /* Check some constraints */
127:   PetscObjectTypeCompare((PetscObject)ksp,KSPPREONLY,&t);
128:   if (!t) SETERRQ(PetscObjectComm((PetscObject)eps),PETSC_ERR_SUP,"EPSGD only works with KSPPREONLY");
129:   return(0);
130: }

134: PetscErrorCode EPSDestroy_GD(EPS eps)
135: {
136:   PetscErrorCode  ierr;

139:   PetscFree(eps->data);
140:   PetscObjectComposeFunction((PetscObject)eps,"EPSGDSetKrylovStart_C",NULL);
141:   PetscObjectComposeFunction((PetscObject)eps,"EPSGDGetKrylovStart_C",NULL);
142:   PetscObjectComposeFunction((PetscObject)eps,"EPSGDSetBOrth_C",NULL);
143:   PetscObjectComposeFunction((PetscObject)eps,"EPSGDGetBOrth_C",NULL);
144:   PetscObjectComposeFunction((PetscObject)eps,"EPSGDSetBlockSize_C",NULL);
145:   PetscObjectComposeFunction((PetscObject)eps,"EPSGDGetBlockSize_C",NULL);
146:   PetscObjectComposeFunction((PetscObject)eps,"EPSGDSetRestart_C",NULL);
147:   PetscObjectComposeFunction((PetscObject)eps,"EPSGDGetRestart_C",NULL);
148:   PetscObjectComposeFunction((PetscObject)eps,"EPSGDSetInitialSize_C",NULL);
149:   PetscObjectComposeFunction((PetscObject)eps,"EPSGDGetInitialSize_C",NULL);
150:   PetscObjectComposeFunction((PetscObject)eps,"EPSGDSetWindowSizes_C",NULL);
151:   PetscObjectComposeFunction((PetscObject)eps,"EPSGDGetWindowSizes_C",NULL);
152:   PetscObjectComposeFunction((PetscObject)eps,"EPSGDSetDoubleExpansion_C",NULL);
153:   PetscObjectComposeFunction((PetscObject)eps,"EPSGDGetDoubleExpansion_C",NULL);
154:   return(0);
155: }

159: /*@
160:    EPSGDSetKrylovStart - Activates or deactivates starting the searching
161:    subspace with a Krylov basis.

163:    Logically Collective on EPS

165:    Input Parameters:
166: +  eps - the eigenproblem solver context
167: -  krylovstart - boolean flag

169:    Options Database Key:
170: .  -eps_gd_krylov_start - Activates starting the searching subspace with a
171:     Krylov basis

173:    Level: advanced

175: .seealso: EPSGDGetKrylovStart()
176: @*/
177: PetscErrorCode EPSGDSetKrylovStart(EPS eps,PetscBool krylovstart)
178: {

184:   PetscTryMethod(eps,"EPSGDSetKrylovStart_C",(EPS,PetscBool),(eps,krylovstart));
185:   return(0);
186: }

190: /*@
191:    EPSGDGetKrylovStart - Returns a flag indicating if the search subspace is started with a
192:    Krylov basis.

194:    Not Collective

196:    Input Parameter:
197: .  eps - the eigenproblem solver context

199:    Output Parameters:
200: .  krylovstart - boolean flag indicating if the search subspace is started
201:    with a Krylov basis

203:    Level: advanced

205: .seealso: EPSGDGetKrylovStart()
206: @*/
207: PetscErrorCode EPSGDGetKrylovStart(EPS eps,PetscBool *krylovstart)
208: {

214:   PetscTryMethod(eps,"EPSGDGetKrylovStart_C",(EPS,PetscBool*),(eps,krylovstart));
215:   return(0);
216: }

220: /*@
221:    EPSGDSetBlockSize - Sets the number of vectors to be added to the searching space
222:    in every iteration.

224:    Logically Collective on EPS

226:    Input Parameters:
227: +  eps - the eigenproblem solver context
228: -  blocksize - number of vectors added to the search space in every iteration

230:    Options Database Key:
231: .  -eps_gd_blocksize - number of vectors added to the search space in every iteration

233:    Level: advanced

235: .seealso: EPSGDSetKrylovStart()
236: @*/
237: PetscErrorCode EPSGDSetBlockSize(EPS eps,PetscInt blocksize)
238: {

244:   PetscTryMethod(eps,"EPSGDSetBlockSize_C",(EPS,PetscInt),(eps,blocksize));
245:   return(0);
246: }

250: /*@
251:    EPSGDGetBlockSize - Returns the number of vectors to be added to the searching space
252:    in every iteration.

254:    Not Collective

256:    Input Parameter:
257: .  eps - the eigenproblem solver context

259:    Output Parameter:
260: .  blocksize - number of vectors added to the search space in every iteration

262:    Level: advanced

264: .seealso: EPSGDSetBlockSize()
265: @*/
266: PetscErrorCode EPSGDGetBlockSize(EPS eps,PetscInt *blocksize)
267: {

273:   PetscTryMethod(eps,"EPSGDGetBlockSize_C",(EPS,PetscInt*),(eps,blocksize));
274:   return(0);
275: }

279: /*@
280:    EPSGDGetRestart - Gets the number of vectors of the searching space after
281:    restarting and the number of vectors saved from the previous iteration.

283:    Not Collective

285:    Input Parameter:
286: .  eps - the eigenproblem solver context

288:    Output Parameter:
289: +  minv - number of vectors of the searching subspace after restarting
290: -  plusk - number of vectors saved from the previous iteration

292:    Level: advanced

294: .seealso: EPSGDSetRestart()
295: @*/
296: PetscErrorCode EPSGDGetRestart(EPS eps,PetscInt *minv,PetscInt *plusk)
297: {

302:   PetscTryMethod(eps,"EPSGDGetRestart_C",(EPS,PetscInt*,PetscInt*),(eps,minv,plusk));
303:   return(0);
304: }

308: /*@
309:    EPSGDSetRestart - Sets the number of vectors of the searching space after
310:    restarting and the number of vectors saved from the previous iteration.

312:    Logically Collective on EPS

314:    Input Parameters:
315: +  eps - the eigenproblem solver context
316: .  minv - number of vectors of the searching subspace after restarting
317: -  plusk - number of vectors saved from the previous iteration

319:    Options Database Keys:
320: +  -eps_gd_minv - number of vectors of the searching subspace after restarting
321: -  -eps_gd_plusk - number of vectors saved from the previous iteration

323:    Level: advanced

325: .seealso: EPSGDSetRestart()
326: @*/
327: PetscErrorCode EPSGDSetRestart(EPS eps,PetscInt minv,PetscInt plusk)
328: {

335:   PetscTryMethod(eps,"EPSGDSetRestart_C",(EPS,PetscInt,PetscInt),(eps,minv,plusk));
336:   return(0);
337: }

341: /*@
342:    EPSGDGetInitialSize - Returns the initial size of the searching space.

344:    Not Collective

346:    Input Parameter:
347: .  eps - the eigenproblem solver context

349:    Output Parameter:
350: .  initialsize - number of vectors of the initial searching subspace

352:    Notes:
353:    If EPSGDGetKrylovStart() is PETSC_FALSE and the user provides vectors with
354:    EPSSetInitialSpace(), up to initialsize vectors will be used; and if the
355:    provided vectors are not enough, the solver completes the subspace with
356:    random vectors. In the case of EPSGDGetKrylovStart() being PETSC_TRUE, the solver
357:    gets the first vector provided by the user or, if not available, a random vector,
358:    and expands the Krylov basis up to initialsize vectors.

360:    Level: advanced

362: .seealso: EPSGDSetInitialSize(), EPSGDGetKrylovStart()
363: @*/
364: PetscErrorCode EPSGDGetInitialSize(EPS eps,PetscInt *initialsize)
365: {

371:   PetscTryMethod(eps,"EPSGDGetInitialSize_C",(EPS,PetscInt*),(eps,initialsize));
372:   return(0);
373: }

377: /*@
378:    EPSGDSetInitialSize - Sets the initial size of the searching space.

380:    Logically Collective on EPS

382:    Input Parameters:
383: +  eps - the eigenproblem solver context
384: -  initialsize - number of vectors of the initial searching subspace

386:    Options Database Key:
387: .  -eps_gd_initial_size - number of vectors of the initial searching subspace

389:    Notes:
390:    If EPSGDGetKrylovStart() is PETSC_FALSE and the user provides vectors with
391:    EPSSetInitialSpace(), up to initialsize vectors will be used; and if the
392:    provided vectors are not enough, the solver completes the subspace with
393:    random vectors. In the case of EPSGDGetKrylovStart() being PETSC_TRUE, the solver
394:    gets the first vector provided by the user or, if not available, a random vector,
395:    and expands the Krylov basis up to initialsize vectors.

397:    Level: advanced

399: .seealso: EPSGDGetInitialSize(), EPSGDGetKrylovStart()
400: @*/
401: PetscErrorCode EPSGDSetInitialSize(EPS eps,PetscInt initialsize)
402: {

408:   PetscTryMethod(eps,"EPSGDSetInitialSize_C",(EPS,PetscInt),(eps,initialsize));
409:   return(0);
410: }

414: /*@
415:    EPSGDSetBOrth - Selects the orthogonalization that will be used in the search
416:    subspace in case of generalized Hermitian problems.

418:    Logically Collective on EPS

420:    Input Parameters:
421: +  eps   - the eigenproblem solver context
422: -  borth - the kind of orthogonalization

424:    Possible values:
425:    The parameter 'borth' can have one of these values

427: +   EPS_ORTH_I - orthogonalization of the search subspace
428: .   EPS_ORTH_B - B-orthogonalization of the search subspace
429: -   EPS_ORTH_BOPT - B-orthogonalization of the search subspace with an alternative method

431:    Options Database Key:
432: .  -eps_gd_borth - Set the orthogonalization used in the search subspace

434:    Notes:
435:    If borth is EPS_ORTH_B, the solver uses a variant of Gram-Schmidt (selected in
436:    IP associated to the EPS) with the inner product defined by the matrix problem B.
437:    If borth is EPS_ORTH_BOPT, it uses another variant of Gram-Schmidt that only performs
438:    one matrix-vector product although more than one reorthogonalization would be done.

440:    Level: advanced

442: .seealso: EPSGDGetBOrth()
443: @*/
444: PetscErrorCode EPSGDSetBOrth(EPS eps,EPSOrthType borth)
445: {

451:   PetscTryMethod(eps,"EPSGDSetBOrth_C",(EPS,EPSOrthType),(eps,borth));
452:   return(0);
453: }

457: /*@
458:    EPSGDGetBOrth - Returns the orthogonalization used in the search
459:    subspace in case of generalized Hermitian problems.

461:    Not Collective

463:    Input Parameter:
464: .  eps - the eigenproblem solver context

466:    Output Parameters:
467: .  borth - the kind of orthogonalization

469:    Notes:
470:    See EPSGDSetBOrth() for possible values of 'borth'.

472:    Level: advanced

474: .seealso: EPSGDSetBOrth(), EPSOrthType
475: @*/
476: PetscErrorCode EPSGDGetBOrth(EPS eps,EPSOrthType *borth)
477: {

483:   PetscTryMethod(eps,"EPSGDGetBOrth_C",(EPS,EPSOrthType*),(eps,borth));
484:   return(0);
485: }

489: /*@
490:    EPSGDGetWindowSizes - Gets the number of converged vectors in the projected
491:    problem (or Rayleigh quotient) and in the projector employed in the correction
492:    equation.

494:    Not Collective

496:    Input Parameter:
497: .  eps - the eigenproblem solver context

499:    Output Parameter:
500: +  pwindow - number of converged vectors in the projector
501: -  qwindow - number of converged vectors in the projected problem

503:    Level: advanced

505: .seealso: EPSGDSetWindowSizes()
506: @*/
507: PetscErrorCode EPSGDGetWindowSizes(EPS eps,PetscInt *pwindow,PetscInt *qwindow)
508: {

513:   PetscTryMethod(eps,"EPSGDGetWindowSizes_C",(EPS,PetscInt*,PetscInt*),(eps,pwindow,qwindow));
514:   return(0);
515: }

519: /*@
520:    EPSGDSetWindowSizes - Sets the number of converged vectors in the projected
521:    problem (or Rayleigh quotient) and in the projector employed in the correction
522:    equation.

524:    Logically Collective on EPS

526:    Input Parameters:
527: +  eps - the eigenproblem solver context
528: .  pwindow - number of converged vectors in the projector
529: -  qwindow - number of converged vectors in the projected problem

531:    Options Database Keys:
532: +  -eps_gd_pwindow - set the number of converged vectors in the projector
533: -  -eps_gd_qwindow - set the number of converged vectors in the projected problem

535:    Level: advanced

537: .seealso: EPSGDGetWindowSizes()
538: @*/
539: PetscErrorCode EPSGDSetWindowSizes(EPS eps,PetscInt pwindow,PetscInt qwindow)
540: {

547:   PetscTryMethod(eps,"EPSGDSetWindowSizes_C",(EPS,PetscInt,PetscInt),(eps,pwindow,qwindow));
548:   return(0);
549: }

553: static PetscErrorCode EPSGDSetDoubleExpansion_GD(EPS eps,PetscBool use_gd2)
554: {

558:   EPSXDSetMethod(eps,use_gd2?DVD_METH_GD2:DVD_METH_GD);
559:   return(0);
560: }

564: static PetscErrorCode EPSGDGetDoubleExpansion_GD(EPS eps,PetscBool *flg)
565: {
566:   Method_t       meth;

570:   EPSXDGetMethod_XD(eps,&meth);
571:   if (meth==DVD_METH_GD2) *flg = PETSC_TRUE;
572:   else *flg = PETSC_FALSE;
573:   return(0);
574: }

578: /*@
579:    EPSGDGetDoubleExpansion - Gets a flag indicating whether the double
580:    expansion variant has been activated or not.

582:    Not Collective

584:    Input Parameter:
585: .  eps - the eigenproblem solver context

587:    Output Parameter:
588: .  flg - the flag

590:    Level: advanced

592: .seealso: EPSGDSetDoubleExpansion()
593: @*/
594: PetscErrorCode EPSGDGetDoubleExpansion(EPS eps,PetscBool *flg)
595: {

601:   PetscTryMethod(eps,"EPSGDGetDoubleExpansion_C",(EPS,PetscBool*),(eps,flg));
602:   return(0);
603: }

607: /*@
608:    EPSGDSetDoubleExpansion - Activate a variant where the search subspace is
609:    expanded with K*[A*x B*x] (double expansion) instead of the classic K*r,
610:    where K is the preconditioner, x the selected approximate eigenvector and
611:    r its associated residual vector.

613:    Logically Collective on EPS

615:    Input Parameters:
616: +  eps - the eigenproblem solver context
617: -  use_gd2 - the boolean flag

619:    Options Database Keys:
620: .  -eps_gd_double_expansion - activate the double-expansion variant of GD

622:    Level: advanced
623: @*/
624: PetscErrorCode EPSGDSetDoubleExpansion(EPS eps,PetscBool use_gd2)
625: {

631:   PetscTryMethod(eps,"EPSGDSetDoubleExpansion_C",(EPS,PetscBool),(eps,use_gd2));
632:   return(0);
633: }

637: PETSC_EXTERN PetscErrorCode EPSCreate_GD(EPS eps)
638: {
639:   PetscErrorCode  ierr;

642:   /* Load the Davidson solver */
643:   EPSCreate_XD(eps);
644:   EPSJDSetFix_JD(eps,0.0);
645:   EPSXDSetMethod(eps,DVD_METH_GD);

647:   /* Overload the GD properties */
648:   eps->ops->setfromoptions       = EPSSetFromOptions_GD;
649:   eps->ops->setup                = EPSSetUp_GD;
650:   eps->ops->destroy              = EPSDestroy_GD;

652:   PetscObjectComposeFunction((PetscObject)eps,"EPSGDSetKrylovStart_C",EPSXDSetKrylovStart_XD);
653:   PetscObjectComposeFunction((PetscObject)eps,"EPSGDGetKrylovStart_C",EPSXDGetKrylovStart_XD);
654:   PetscObjectComposeFunction((PetscObject)eps,"EPSGDSetBOrth_C",EPSXDSetBOrth_XD);
655:   PetscObjectComposeFunction((PetscObject)eps,"EPSGDGetBOrth_C",EPSXDGetBOrth_XD);
656:   PetscObjectComposeFunction((PetscObject)eps,"EPSGDSetBlockSize_C",EPSXDSetBlockSize_XD);
657:   PetscObjectComposeFunction((PetscObject)eps,"EPSGDGetBlockSize_C",EPSXDGetBlockSize_XD);
658:   PetscObjectComposeFunction((PetscObject)eps,"EPSGDSetRestart_C",EPSXDSetRestart_XD);
659:   PetscObjectComposeFunction((PetscObject)eps,"EPSGDGetRestart_C",EPSXDGetRestart_XD);
660:   PetscObjectComposeFunction((PetscObject)eps,"EPSGDSetInitialSize_C",EPSXDSetInitialSize_XD);
661:   PetscObjectComposeFunction((PetscObject)eps,"EPSGDGetInitialSize_C",EPSXDGetInitialSize_XD);
662:   PetscObjectComposeFunction((PetscObject)eps,"EPSGDSetWindowSizes_C",EPSXDSetWindowSizes_XD);
663:   PetscObjectComposeFunction((PetscObject)eps,"EPSGDGetWindowSizes_C",EPSXDGetWindowSizes_XD);
664:   PetscObjectComposeFunction((PetscObject)eps,"EPSGDSetDoubleExpansion_C",EPSGDSetDoubleExpansion_GD);
665:   PetscObjectComposeFunction((PetscObject)eps,"EPSGDGetDoubleExpansion_C",EPSGDGetDoubleExpansion_GD);
666:   return(0);
667: }