Actual source code: gd.c
slepc-3.10.1 2018-10-23
Report Typos and Errors

      1: /*
      2:    - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
      3:    SLEPc - Scalable Library for Eigenvalue Problem Computations
      4:    Copyright (c) 2002-2018, 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: PETSC_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: }