Actual source code: gd.c

slepc-3.11.2 2019-07-30
Report Typos and Errors
  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 EPS

149:    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 EPS

206:    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 EPS

261:    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 EPS

318:    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 EPS

388:    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 EPS

454:    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: }