Date: 2023-01-26T12:18:31+00:00

Actual source code: epssetup.c
slepc-3.18.2 2023-01-26
Report Typos and Errors

      1: /*
      2:    - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
      3:    SLEPc - Scalable Library for Eigenvalue Problem Computations
      4:    Copyright (c) 2002-, 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:    EPS routines related to problem setup
     12: */

     14: #include <slepc/private/epsimpl.h>

     16: /*
     17:    Let the solver choose the ST type that should be used by default,
     18:    otherwise set it to SHIFT.
     19:    This is called at EPSSetFromOptions (before STSetFromOptions)
     20:    and also at EPSSetUp (in case EPSSetFromOptions was not called).
     21: */
     22: PetscErrorCode EPSSetDefaultST(EPS eps)
     23: {
     24:   PetscTryTypeMethod(eps,setdefaultst);
     25:   if (!((PetscObject)eps->st)->type_name) STSetType(eps->st,STSHIFT);
     26:   return 0;
     27: }

     29: /*
     30:    This is done by preconditioned eigensolvers that use the PC only.
     31:    It sets STPRECOND with KSPPREONLY.
     32: */
     33: PetscErrorCode EPSSetDefaultST_Precond(EPS eps)
     34: {
     35:   KSP            ksp;

     37:   if (!((PetscObject)eps->st)->type_name) STSetType(eps->st,STPRECOND);
     38:   STGetKSP(eps->st,&ksp);
     39:   if (!((PetscObject)ksp)->type_name) KSPSetType(ksp,KSPPREONLY);
     40:   return 0;
     41: }

     43: /*
     44:    This is done by preconditioned eigensolvers that can also use the KSP.
     45:    It sets STPRECOND with the default KSP (GMRES) and maxit=5.
     46: */
     47: PetscErrorCode EPSSetDefaultST_GMRES(EPS eps)
     48: {
     49:   KSP            ksp;

     51:   if (!((PetscObject)eps->st)->type_name) STSetType(eps->st,STPRECOND);
     52:   STPrecondSetKSPHasMat(eps->st,PETSC_TRUE);
     53:   STGetKSP(eps->st,&ksp);
     54:   if (!((PetscObject)ksp)->type_name) {
     55:     KSPSetType(ksp,KSPGMRES);
     56:     KSPSetTolerances(ksp,PETSC_DEFAULT,PETSC_DEFAULT,PETSC_DEFAULT,5);
     57:   }
     58:   return 0;
     59: }

     61: #if defined(SLEPC_HAVE_SCALAPACK) || defined(SLEPC_HAVE_ELPA) || defined(SLEPC_HAVE_ELEMENTAL) || defined(SLEPC_HAVE_EVSL)
     62: /*
     63:    This is for direct eigensolvers that work with A and B directly, so
     64:    no need to factorize B.
     65: */
     66: PetscErrorCode EPSSetDefaultST_NoFactor(EPS eps)
     67: {
     68:   KSP            ksp;
     69:   PC             pc;

     71:   if (!((PetscObject)eps->st)->type_name) STSetType(eps->st,STSHIFT);
     72:   STGetKSP(eps->st,&ksp);
     73:   if (!((PetscObject)ksp)->type_name) KSPSetType(ksp,KSPPREONLY);
     74:   KSPGetPC(ksp,&pc);
     75:   if (!((PetscObject)pc)->type_name) PCSetType(pc,PCNONE);
     76:   return 0;
     77: }
     78: #endif

     80: /*
     81:    Check that the ST selected by the user is compatible with the EPS solver and options
     82: */
     83: PetscErrorCode EPSCheckCompatibleST(EPS eps)
     84: {
     85:   PetscBool      precond,shift,sinvert,cayley,lyapii;
     86: #if defined(PETSC_USE_COMPLEX)
     87:   PetscScalar    sigma;
     88: #endif

     90:   PetscObjectTypeCompare((PetscObject)eps->st,STPRECOND,&precond);
     91:   PetscObjectTypeCompare((PetscObject)eps->st,STSHIFT,&shift);
     92:   PetscObjectTypeCompare((PetscObject)eps->st,STSINVERT,&sinvert);
     93:   PetscObjectTypeCompare((PetscObject)eps->st,STCAYLEY,&cayley);

     95:   /* preconditioned eigensolvers */

     99:   /* harmonic extraction */

    102:   /* real shifts in Hermitian problems */
    103: #if defined(PETSC_USE_COMPLEX)
    104:   STGetShift(eps->st,&sigma);
    106: #endif

    108:   /* Cayley with PGNHEP */

    111:   /* make sure that the user does not specify smallest magnitude with shift-and-invert */
    112:   if ((cayley || sinvert) && (eps->categ==EPS_CATEGORY_KRYLOV || eps->categ==EPS_CATEGORY_OTHER)) {
    113:     PetscObjectTypeCompare((PetscObject)eps,EPSLYAPII,&lyapii);
    115:   }
    116:   return 0;
    117: }

    119: /*
    120:    MatEstimateSpectralRange_EPS: estimate the spectral range [left,right] of a
    121:    symmetric/Hermitian matrix A using an auxiliary EPS object
    122: */
    123: PetscErrorCode MatEstimateSpectralRange_EPS(Mat A,PetscReal *left,PetscReal *right)
    124: {
    125:   PetscInt       nconv;
    126:   PetscScalar    eig0;
    127:   PetscReal      tol=1e-3,errest=tol;
    128:   EPS            eps;

    130:   *left = 0.0; *right = 0.0;
    131:   EPSCreate(PetscObjectComm((PetscObject)A),&eps);
    132:   EPSSetOptionsPrefix(eps,"eps_filter_");
    133:   EPSSetOperators(eps,A,NULL);
    134:   EPSSetProblemType(eps,EPS_HEP);
    135:   EPSSetTolerances(eps,tol,50);
    136:   EPSSetConvergenceTest(eps,EPS_CONV_ABS);
    137:   EPSSetWhichEigenpairs(eps,EPS_SMALLEST_REAL);
    138:   EPSSolve(eps);
    139:   EPSGetConverged(eps,&nconv);
    140:   if (nconv>0) {
    141:     EPSGetEigenvalue(eps,0,&eig0,NULL);
    142:     EPSGetErrorEstimate(eps,0,&errest);
    143:   } else eig0 = eps->eigr[0];
    144:   *left = PetscRealPart(eig0)-errest;
    145:   EPSSetWhichEigenpairs(eps,EPS_LARGEST_REAL);
    146:   EPSSolve(eps);
    147:   EPSGetConverged(eps,&nconv);
    148:   if (nconv>0) {
    149:     EPSGetEigenvalue(eps,0,&eig0,NULL);
    150:     EPSGetErrorEstimate(eps,0,&errest);
    151:   } else eig0 = eps->eigr[0];
    152:   *right = PetscRealPart(eig0)+errest;
    153:   EPSDestroy(&eps);
    154:   return 0;
    155: }

    157: /*
    158:    EPSSetUpSort_Basic: configure the EPS sorting criterion according to 'which'
    159: */
    160: PetscErrorCode EPSSetUpSort_Basic(EPS eps)
    161: {
    162:   switch (eps->which) {
    163:     case EPS_LARGEST_MAGNITUDE:
    164:       eps->sc->comparison    = SlepcCompareLargestMagnitude;
    165:       eps->sc->comparisonctx = NULL;
    166:       break;
    167:     case EPS_SMALLEST_MAGNITUDE:
    168:       eps->sc->comparison    = SlepcCompareSmallestMagnitude;
    169:       eps->sc->comparisonctx = NULL;
    170:       break;
    171:     case EPS_LARGEST_REAL:
    172:       eps->sc->comparison    = SlepcCompareLargestReal;
    173:       eps->sc->comparisonctx = NULL;
    174:       break;
    175:     case EPS_SMALLEST_REAL:
    176:       eps->sc->comparison    = SlepcCompareSmallestReal;
    177:       eps->sc->comparisonctx = NULL;
    178:       break;
    179:     case EPS_LARGEST_IMAGINARY:
    180:       eps->sc->comparison    = SlepcCompareLargestImaginary;
    181:       eps->sc->comparisonctx = NULL;
    182:       break;
    183:     case EPS_SMALLEST_IMAGINARY:
    184:       eps->sc->comparison    = SlepcCompareSmallestImaginary;
    185:       eps->sc->comparisonctx = NULL;
    186:       break;
    187:     case EPS_TARGET_MAGNITUDE:
    188:       eps->sc->comparison    = SlepcCompareTargetMagnitude;
    189:       eps->sc->comparisonctx = &eps->target;
    190:       break;
    191:     case EPS_TARGET_REAL:
    192:       eps->sc->comparison    = SlepcCompareTargetReal;
    193:       eps->sc->comparisonctx = &eps->target;
    194:       break;
    195:     case EPS_TARGET_IMAGINARY:
    196: #if defined(PETSC_USE_COMPLEX)
    197:       eps->sc->comparison    = SlepcCompareTargetImaginary;
    198:       eps->sc->comparisonctx = &eps->target;
    199: #endif
    200:       break;
    201:     case EPS_ALL:
    202:       eps->sc->comparison    = SlepcCompareSmallestReal;
    203:       eps->sc->comparisonctx = NULL;
    204:       break;
    205:     case EPS_WHICH_USER:
    206:       break;
    207:   }
    208:   eps->sc->map    = NULL;
    209:   eps->sc->mapobj = NULL;
    210:   return 0;
    211: }

    213: /*
    214:    EPSSetUpSort_Default: configure both EPS and DS sorting criterion
    215: */
    216: PetscErrorCode EPSSetUpSort_Default(EPS eps)
    217: {
    218:   SlepcSC        sc;
    219:   PetscBool      istrivial;

    221:   /* fill sorting criterion context */
    222:   EPSSetUpSort_Basic(eps);
    223:   /* fill sorting criterion for DS */
    224:   DSGetSlepcSC(eps->ds,&sc);
    225:   RGIsTrivial(eps->rg,&istrivial);
    226:   sc->rg            = istrivial? NULL: eps->rg;
    227:   sc->comparison    = eps->sc->comparison;
    228:   sc->comparisonctx = eps->sc->comparisonctx;
    229:   sc->map           = SlepcMap_ST;
    230:   sc->mapobj        = (PetscObject)eps->st;
    231:   return 0;
    232: }

    234: /*@
    235:    EPSSetUp - Sets up all the internal data structures necessary for the
    236:    execution of the eigensolver. Then calls STSetUp() for any set-up
    237:    operations associated to the ST object.

    239:    Collective on eps

    241:    Input Parameter:
    242: .  eps   - eigenproblem solver context

    244:    Notes:
    245:    This function need not be called explicitly in most cases, since EPSSolve()
    246:    calls it. It can be useful when one wants to measure the set-up time
    247:    separately from the solve time.

    249:    Level: developer

    251: .seealso: EPSCreate(), EPSSolve(), EPSDestroy(), STSetUp(), EPSSetInitialSpace()
    252: @*/
    253: PetscErrorCode EPSSetUp(EPS eps)
    254: {
    255:   Mat            A,B;
    256:   PetscInt       k,nmat;
    257:   PetscBool      flg;

    260:   if (eps->state) return 0;
    261:   PetscLogEventBegin(EPS_SetUp,eps,0,0,0);

    263:   /* reset the convergence flag from the previous solves */
    264:   eps->reason = EPS_CONVERGED_ITERATING;

    266:   /* Set default solver type (EPSSetFromOptions was not called) */
    267:   if (!((PetscObject)eps)->type_name) EPSSetType(eps,EPSKRYLOVSCHUR);
    268:   if (!eps->st) EPSGetST(eps,&eps->st);
    269:   EPSSetDefaultST(eps);

    271:   STSetTransform(eps->st,PETSC_TRUE);
    272:   if (eps->useds && !eps->ds) EPSGetDS(eps,&eps->ds);
    273:   if (eps->twosided) {
    275:   }
    276:   if (!eps->rg) EPSGetRG(eps,&eps->rg);
    277:   if (!((PetscObject)eps->rg)->type_name) RGSetType(eps->rg,RGINTERVAL);

    279:   /* Set problem dimensions */
    280:   STGetNumMatrices(eps->st,&nmat);
    282:   STMatGetSize(eps->st,&eps->n,NULL);
    283:   STMatGetLocalSize(eps->st,&eps->nloc,NULL);

    285:   /* Set default problem type */
    286:   if (!eps->problem_type) {
    287:     if (nmat==1) EPSSetProblemType(eps,EPS_NHEP);
    288:     else EPSSetProblemType(eps,EPS_GNHEP);
    289:   } else if (nmat==1 && eps->isgeneralized) {
    290:     PetscInfo(eps,"Eigenproblem set as generalized but no matrix B was provided; reverting to a standard eigenproblem\n");
    291:     eps->isgeneralized = PETSC_FALSE;
    292:     eps->problem_type = eps->ishermitian? EPS_HEP: EPS_NHEP;

    295:   if (eps->nev > eps->n) eps->nev = eps->n;
    296:   if (eps->ncv > eps->n) eps->ncv = eps->n;

    298:   /* check some combinations of eps->which */

    301:   /* initialization of matrix norms */
    302:   if (eps->conv==EPS_CONV_NORM) {
    303:     if (!eps->nrma) {
    304:       STGetMatrix(eps->st,0,&A);
    305:       MatNorm(A,NORM_INFINITY,&eps->nrma);
    306:     }
    307:     if (nmat>1 && !eps->nrmb) {
    308:       STGetMatrix(eps->st,1,&B);
    309:       MatNorm(B,NORM_INFINITY,&eps->nrmb);
    310:     }
    311:   }

    313:   /* call specific solver setup */
    314:   PetscUseTypeMethod(eps,setup);

    316:   /* if purification is set, check that it really makes sense */
    317:   if (eps->purify) {
    318:     if (eps->categ==EPS_CATEGORY_PRECOND || eps->categ==EPS_CATEGORY_CONTOUR) eps->purify = PETSC_FALSE;
    319:     else {
    320:       if (!eps->isgeneralized) eps->purify = PETSC_FALSE;
    321:       else if (!eps->ishermitian && !eps->ispositive) eps->purify = PETSC_FALSE;
    322:       else {
    323:         PetscObjectTypeCompare((PetscObject)eps->st,STCAYLEY,&flg);
    324:         if (flg) eps->purify = PETSC_FALSE;
    325:       }
    326:     }
    327:   }

    329:   /* set tolerance if not yet set */
    330:   if (eps->tol==PETSC_DEFAULT) eps->tol = SLEPC_DEFAULT_TOL;

    332:   /* set up sorting criterion */
    333:   PetscTryTypeMethod(eps,setupsort);

    335:   /* Build balancing matrix if required */
    336:   if (eps->balance!=EPS_BALANCE_USER) {
    337:     STSetBalanceMatrix(eps->st,NULL);
    338:     if (!eps->ishermitian && (eps->balance==EPS_BALANCE_ONESIDE || eps->balance==EPS_BALANCE_TWOSIDE)) {
    339:       if (!eps->D) BVCreateVec(eps->V,&eps->D);
    340:       EPSBuildBalance_Krylov(eps);
    341:       STSetBalanceMatrix(eps->st,eps->D);
    342:     }
    343:   }

    345:   /* Setup ST */
    346:   STSetUp(eps->st);
    347:   EPSCheckCompatibleST(eps);

    349:   /* process deflation and initial vectors */
    350:   if (eps->nds<0) {
    351:     k = -eps->nds;
    352:     BVInsertConstraints(eps->V,&k,eps->defl);
    353:     SlepcBasisDestroy_Private(&eps->nds,&eps->defl);
    354:     eps->nds = k;
    355:     STCheckNullSpace(eps->st,eps->V);
    356:   }
    357:   if (eps->nini<0) {
    358:     k = -eps->nini;
    360:     BVInsertVecs(eps->V,0,&k,eps->IS,PETSC_TRUE);
    361:     SlepcBasisDestroy_Private(&eps->nini,&eps->IS);
    362:     eps->nini = k;
    363:   }
    364:   if (eps->twosided && eps->ninil<0) {
    365:     k = -eps->ninil;
    367:     BVInsertVecs(eps->W,0,&k,eps->ISL,PETSC_TRUE);
    368:     SlepcBasisDestroy_Private(&eps->ninil,&eps->ISL);
    369:     eps->ninil = k;
    370:   }

    372:   PetscLogEventEnd(EPS_SetUp,eps,0,0,0);
    373:   eps->state = EPS_STATE_SETUP;
    374:   return 0;
    375: }

    377: /*@
    378:    EPSSetOperators - Sets the matrices associated with the eigenvalue problem.

    380:    Collective on eps

    382:    Input Parameters:
    383: +  eps - the eigenproblem solver context
    384: .  A  - the matrix associated with the eigensystem
    385: -  B  - the second matrix in the case of generalized eigenproblems

    387:    Notes:
    388:    To specify a standard eigenproblem, use NULL for parameter B.

    390:    It must be called before EPSSetUp(). If it is called again after EPSSetUp() and
    391:    the matrix sizes have changed then the EPS object is reset.

    393:    Level: beginner

    395: .seealso: EPSSolve(), EPSSetUp(), EPSReset(), EPSGetST(), STGetMatrix()
    396: @*/
    397: PetscErrorCode EPSSetOperators(EPS eps,Mat A,Mat B)
    398: {
    399:   PetscInt       m,n,m0,mloc,nloc,mloc0,nmat;
    400:   Mat            mat[2];

    408:   /* Check matrix sizes */
    409:   MatGetSize(A,&m,&n);
    410:   MatGetLocalSize(A,&mloc,&nloc);
    413:   if (B) {
    414:     MatGetSize(B,&m0,&n);
    415:     MatGetLocalSize(B,&mloc0,&nloc);
    420:   }
    421:   if (eps->state && (n!=eps->n || nloc!=eps->nloc)) EPSReset(eps);
    422:   eps->nrma = 0.0;
    423:   eps->nrmb = 0.0;
    424:   if (!eps->st) EPSGetST(eps,&eps->st);
    425:   mat[0] = A;
    426:   if (B) {
    427:     mat[1] = B;
    428:     nmat = 2;
    429:   } else nmat = 1;
    430:   STSetMatrices(eps->st,nmat,mat);
    431:   eps->state = EPS_STATE_INITIAL;
    432:   return 0;
    433: }

    435: /*@
    436:    EPSGetOperators - Gets the matrices associated with the eigensystem.

    438:    Collective on eps

    440:    Input Parameter:
    441: .  eps - the EPS context

    443:    Output Parameters:
    444: +  A  - the matrix associated with the eigensystem
    445: -  B  - the second matrix in the case of generalized eigenproblems

    447:    Note:
    448:    Does not increase the reference count of the matrices, so you should not destroy them.

    450:    Level: intermediate

    452: .seealso: EPSSolve(), EPSGetST(), STGetMatrix(), STSetMatrices()
    453: @*/
    454: PetscErrorCode EPSGetOperators(EPS eps,Mat *A,Mat *B)
    455: {
    456:   ST             st;
    457:   PetscInt       k;

    460:   EPSGetST(eps,&st);
    461:   STGetNumMatrices(st,&k);
    462:   if (A) {
    463:     if (k<1) *A = NULL;
    464:     else STGetMatrix(st,0,A);
    465:   }
    466:   if (B) {
    467:     if (k<2) *B = NULL;
    468:     else STGetMatrix(st,1,B);
    469:   }
    470:   return 0;
    471: }

    473: /*@C
    474:    EPSSetDeflationSpace - Specify a basis of vectors that constitute the deflation
    475:    space.

    477:    Collective on eps

    479:    Input Parameters:
    480: +  eps - the eigenproblem solver context
    481: .  n   - number of vectors
    482: -  v   - set of basis vectors of the deflation space

    484:    Notes:
    485:    When a deflation space is given, the eigensolver seeks the eigensolution
    486:    in the restriction of the problem to the orthogonal complement of this
    487:    space. This can be used for instance in the case that an invariant
    488:    subspace is known beforehand (such as the nullspace of the matrix).

    490:    These vectors do not persist from one EPSSolve() call to the other, so the
    491:    deflation space should be set every time.

    493:    The vectors do not need to be mutually orthonormal, since they are explicitly
    494:    orthonormalized internally.

    496:    Level: intermediate

    498: .seealso: EPSSetInitialSpace()
    499: @*/
    500: PetscErrorCode EPSSetDeflationSpace(EPS eps,PetscInt n,Vec v[])
    501: {
    505:   if (n>0) {
    508:   }
    509:   SlepcBasisReference_Private(n,v,&eps->nds,&eps->defl);
    510:   if (n>0) eps->state = EPS_STATE_INITIAL;
    511:   return 0;
    512: }

    514: /*@C
    515:    EPSSetInitialSpace - Specify a basis of vectors that constitute the initial
    516:    space, that is, the subspace from which the solver starts to iterate.

    518:    Collective on eps

    520:    Input Parameters:
    521: +  eps - the eigenproblem solver context
    522: .  n   - number of vectors
    523: -  is  - set of basis vectors of the initial space

    525:    Notes:
    526:    Some solvers start to iterate on a single vector (initial vector). In that case,
    527:    the other vectors are ignored.

    529:    These vectors do not persist from one EPSSolve() call to the other, so the
    530:    initial space should be set every time.

    532:    The vectors do not need to be mutually orthonormal, since they are explicitly
    533:    orthonormalized internally.

    535:    Common usage of this function is when the user can provide a rough approximation
    536:    of the wanted eigenspace. Then, convergence may be faster.

    538:    Level: intermediate

    540: .seealso: EPSSetLeftInitialSpace(), EPSSetDeflationSpace()
    541: @*/
    542: PetscErrorCode EPSSetInitialSpace(EPS eps,PetscInt n,Vec is[])
    543: {
    547:   if (n>0) {
    550:   }
    551:   SlepcBasisReference_Private(n,is,&eps->nini,&eps->IS);
    552:   if (n>0) eps->state = EPS_STATE_INITIAL;
    553:   return 0;
    554: }

    556: /*@C
    557:    EPSSetLeftInitialSpace - Specify a basis of vectors that constitute the left
    558:    initial space, used by two-sided solvers to start the left subspace.

    560:    Collective on eps

    562:    Input Parameters:
    563: +  eps - the eigenproblem solver context
    564: .  n   - number of vectors
    565: -  isl - set of basis vectors of the left initial space

    567:    Notes:
    568:    Left initial vectors are used to initiate the left search space in two-sided
    569:    eigensolvers. Users should pass here an approximation of the left eigenspace,
    570:    if available.

    572:    The same comments in EPSSetInitialSpace() are applicable here.

    574:    Level: intermediate

    576: .seealso: EPSSetInitialSpace(), EPSSetTwoSided()
    577: @*/
    578: PetscErrorCode EPSSetLeftInitialSpace(EPS eps,PetscInt n,Vec isl[])
    579: {
    583:   if (n>0) {
    586:   }
    587:   SlepcBasisReference_Private(n,isl,&eps->ninil,&eps->ISL);
    588:   if (n>0) eps->state = EPS_STATE_INITIAL;
    589:   return 0;
    590: }

    592: /*
    593:   EPSSetDimensions_Default - Set reasonable values for ncv, mpd if not set
    594:   by the user. This is called at setup.
    595:  */
    596: PetscErrorCode EPSSetDimensions_Default(EPS eps,PetscInt nev,PetscInt *ncv,PetscInt *mpd)
    597: {
    598:   PetscBool      krylov;

    600:   if (*ncv!=PETSC_DEFAULT) { /* ncv set */
    601:     PetscObjectTypeCompareAny((PetscObject)eps,&krylov,EPSKRYLOVSCHUR,EPSARNOLDI,EPSLANCZOS,"");
    602:     if (krylov) {
    604:     } else {
    606:     }
    607:   } else if (*mpd!=PETSC_DEFAULT) { /* mpd set */
    608:     *ncv = PetscMin(eps->n,nev+(*mpd));
    609:   } else { /* neither set: defaults depend on nev being small or large */
    610:     if (nev<500) *ncv = PetscMin(eps->n,PetscMax(2*nev,nev+15));
    611:     else {
    612:       *mpd = 500;
    613:       *ncv = PetscMin(eps->n,nev+(*mpd));
    614:     }
    615:   }
    616:   if (*mpd==PETSC_DEFAULT) *mpd = *ncv;
    617:   return 0;
    618: }

    620: /*@
    621:    EPSAllocateSolution - Allocate memory storage for common variables such
    622:    as eigenvalues and eigenvectors.

    624:    Collective on eps

    626:    Input Parameters:
    627: +  eps   - eigensolver context
    628: -  extra - number of additional positions, used for methods that require a
    629:            working basis slightly larger than ncv

    631:    Developer Notes:
    632:    This is SLEPC_EXTERN because it may be required by user plugin EPS
    633:    implementations.

    635:    Level: developer

    637: .seealso: EPSSetUp()
    638: @*/
    639: PetscErrorCode EPSAllocateSolution(EPS eps,PetscInt extra)
    640: {
    641:   PetscInt       oldsize,requested;
    642:   PetscRandom    rand;
    643:   Vec            t;

    645:   requested = eps->ncv + extra;

    647:   /* oldsize is zero if this is the first time setup is called */
    648:   BVGetSizes(eps->V,NULL,NULL,&oldsize);

    650:   /* allocate space for eigenvalues and friends */
    651:   if (requested != oldsize || !eps->eigr) {
    652:     PetscFree4(eps->eigr,eps->eigi,eps->errest,eps->perm);
    653:     PetscMalloc4(requested,&eps->eigr,requested,&eps->eigi,requested,&eps->errest,requested,&eps->perm);
    654:   }

    656:   /* workspace for the case of arbitrary selection */
    657:   if (eps->arbitrary) {
    658:     if (eps->rr) PetscFree2(eps->rr,eps->ri);
    659:     PetscMalloc2(requested,&eps->rr,requested,&eps->ri);
    660:   }

    662:   /* allocate V */
    663:   if (!eps->V) EPSGetBV(eps,&eps->V);
    664:   if (!oldsize) {
    665:     if (!((PetscObject)(eps->V))->type_name) BVSetType(eps->V,BVSVEC);
    666:     STMatCreateVecsEmpty(eps->st,&t,NULL);
    667:     BVSetSizesFromVec(eps->V,t,requested);
    668:     VecDestroy(&t);
    669:   } else BVResize(eps->V,requested,PETSC_FALSE);

    671:   /* allocate W */
    672:   if (eps->twosided) {
    673:     BVGetRandomContext(eps->V,&rand);  /* make sure the random context is available when duplicating */
    674:     BVDestroy(&eps->W);
    675:     BVDuplicate(eps->V,&eps->W);
    676:   }
    677:   return 0;
    678: }