Date: 2022-08-09T09:05:54+00:00

Actual source code: slp.c
slepc-3.17.2 2022-08-09
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:    SLEPc nonlinear eigensolver: "slp"

     13:    Method: Successive linear problems

     15:    Algorithm:

     17:        Newton-type iteration based on first order Taylor approximation.

     19:    References:

     21:        [1] A. Ruhe, "Algorithms for the nonlinear eigenvalue problem", SIAM J.
     22:            Numer. Anal. 10(4):674-689, 1973.
     23: */

     25: #include <slepc/private/nepimpl.h>
     26: #include <../src/nep/impls/nepdefl.h>
     27: #include "slp.h"

     29: typedef struct {
     30:   NEP_EXT_OP extop;
     31:   Vec        w;
     32: } NEP_SLP_MATSHELL;

     34: PetscErrorCode NEPSetUp_SLP(NEP nep)
     35: {
     36:   NEP_SLP        *ctx = (NEP_SLP*)nep->data;
     37:   PetscBool      flg;
     38:   ST             st;

     40:   if (nep->ncv!=PETSC_DEFAULT) PetscInfo(nep,"Setting ncv = nev, ignoring user-provided value\n");
     41:   nep->ncv = nep->nev;
     42:   if (nep->mpd!=PETSC_DEFAULT) PetscInfo(nep,"Setting mpd = nev, ignoring user-provided value\n");
     43:   nep->mpd = nep->nev;
     45:   if (nep->max_it==PETSC_DEFAULT) nep->max_it = PetscMax(5000,2*nep->n/nep->ncv);
     46:   if (!nep->which) nep->which = NEP_TARGET_MAGNITUDE;
     48:   NEPCheckUnsupported(nep,NEP_FEATURE_REGION);

     50:   if (!ctx->eps) NEPSLPGetEPS(nep,&ctx->eps);
     51:   EPSGetST(ctx->eps,&st);
     52:   PetscObjectTypeCompareAny((PetscObject)st,&flg,STSINVERT,STCAYLEY,"");
     54:   EPSSetDimensions(ctx->eps,1,PETSC_DECIDE,PETSC_DECIDE);
     55:   EPSSetWhichEigenpairs(ctx->eps,EPS_LARGEST_MAGNITUDE);
     56:   EPSSetTolerances(ctx->eps,SlepcDefaultTol(nep->tol)/10.0,nep->max_it);
     57:   if (nep->tol==PETSC_DEFAULT) nep->tol = SLEPC_DEFAULT_TOL;
     58:   if (ctx->deftol==PETSC_DEFAULT) ctx->deftol = nep->tol;

     60:   if (nep->twosided) {
     61:     nep->ops->solve = NEPSolve_SLP_Twosided;
     62:     nep->ops->computevectors = NULL;
     63:     if (!ctx->epsts) NEPSLPGetEPSLeft(nep,&ctx->epsts);
     64:     EPSGetST(ctx->epsts,&st);
     65:     PetscObjectTypeCompareAny((PetscObject)st,&flg,STSINVERT,STCAYLEY,"");
     67:     EPSSetDimensions(ctx->epsts,1,PETSC_DECIDE,PETSC_DECIDE);
     68:     EPSSetWhichEigenpairs(ctx->epsts,EPS_LARGEST_MAGNITUDE);
     69:     EPSSetTolerances(ctx->epsts,SlepcDefaultTol(nep->tol)/10.0,nep->max_it);
     70:   } else {
     71:     nep->ops->solve = NEPSolve_SLP;
     72:     nep->ops->computevectors = NEPComputeVectors_Schur;
     73:   }
     74:   NEPAllocateSolution(nep,0);
     75:   PetscFunctionReturn(0);
     76: }

     78: static PetscErrorCode MatMult_SLP(Mat M,Vec x,Vec y)
     79: {
     80:   NEP_SLP_MATSHELL *ctx;

     82:   MatShellGetContext(M,&ctx);
     83:   MatMult(ctx->extop->MJ,x,ctx->w);
     84:   NEPDeflationFunctionSolve(ctx->extop,ctx->w,y);
     85:   PetscFunctionReturn(0);
     86: }

     88: static PetscErrorCode MatDestroy_SLP(Mat M)
     89: {
     90:   NEP_SLP_MATSHELL *ctx;

     92:   MatShellGetContext(M,&ctx);
     93:   VecDestroy(&ctx->w);
     94:   PetscFree(ctx);
     95:   PetscFunctionReturn(0);
     96: }

     98: #if defined(PETSC_HAVE_CUDA)
     99: static PetscErrorCode MatCreateVecs_SLP(Mat M,Vec *left,Vec *right)
    100: {
    101:   NEP_SLP_MATSHELL *ctx;

    103:   MatShellGetContext(M,&ctx);
    104:   if (right) VecDuplicate(ctx->w,right);
    105:   if (left) VecDuplicate(ctx->w,left);
    106:   PetscFunctionReturn(0);
    107: }
    108: #endif

    110: static PetscErrorCode NEPSLPSetUpLinearEP(NEP nep,NEP_EXT_OP extop,PetscScalar lambda,Vec u,PetscBool ini)
    111: {
    112:   NEP_SLP          *slpctx = (NEP_SLP*)nep->data;
    113:   Mat              Mshell;
    114:   PetscInt         nloc,mloc;
    115:   NEP_SLP_MATSHELL *shellctx;

    117:   if (ini) {
    118:     /* Create mat shell */
    119:     PetscNew(&shellctx);
    120:     shellctx->extop = extop;
    121:     NEPDeflationCreateVec(extop,&shellctx->w);
    122:     MatGetLocalSize(nep->function,&mloc,&nloc);
    123:     nloc += extop->szd; mloc += extop->szd;
    124:     MatCreateShell(PetscObjectComm((PetscObject)nep),nloc,mloc,PETSC_DETERMINE,PETSC_DETERMINE,shellctx,&Mshell);
    125:     MatShellSetOperation(Mshell,MATOP_MULT,(void(*)(void))MatMult_SLP);
    126:     MatShellSetOperation(Mshell,MATOP_DESTROY,(void(*)(void))MatDestroy_SLP);
    127: #if defined(PETSC_HAVE_CUDA)
    128:     MatShellSetOperation(Mshell,MATOP_CREATE_VECS,(void(*)(void))MatCreateVecs_SLP);
    129: #endif
    130:     EPSSetOperators(slpctx->eps,Mshell,NULL);
    131:     MatDestroy(&Mshell);
    132:   }
    133:   NEPDeflationSolveSetUp(extop,lambda);
    134:   NEPDeflationComputeJacobian(extop,lambda,NULL);
    135:   EPSSetInitialSpace(slpctx->eps,1,&u);
    136:   PetscFunctionReturn(0);
    137: }

    139: PetscErrorCode NEPSolve_SLP(NEP nep)
    140: {
    141:   NEP_SLP           *ctx = (NEP_SLP*)nep->data;
    142:   Mat               F,H;
    143:   Vec               uu,u,r;
    144:   PetscScalar       sigma,lambda,mu,im,*Ap;
    145:   const PetscScalar *Hp;
    146:   PetscReal         resnorm;
    147:   PetscInt          nconv,ldh,ldds,i,j;
    148:   PetscBool         skip=PETSC_FALSE,lock=PETSC_FALSE;
    149:   NEP_EXT_OP        extop=NULL;    /* Extended operator for deflation */

    151:   /* get initial approximation of eigenvalue and eigenvector */
    152:   NEPGetDefaultShift(nep,&sigma);
    153:   if (!nep->nini) BVSetRandomColumn(nep->V,0);
    154:   lambda = sigma;
    155:   if (!ctx->ksp) NEPSLPGetKSP(nep,&ctx->ksp);
    156:   NEPDeflationInitialize(nep,nep->V,ctx->ksp,PETSC_TRUE,nep->nev,&extop);
    157:   NEPDeflationCreateVec(extop,&u);
    158:   VecDuplicate(u,&r);
    159:   BVGetColumn(nep->V,0,&uu);
    160:   NEPDeflationCopyToExtendedVec(extop,uu,NULL,u,PETSC_FALSE);
    161:   BVRestoreColumn(nep->V,0,&uu);

    163:   /* Restart loop */
    164:   while (nep->reason == NEP_CONVERGED_ITERATING) {
    165:     nep->its++;

    167:     /* form residual,  r = T(lambda)*u (used in convergence test only) */
    168:     NEPDeflationComputeFunction(extop,lambda,&F);
    169:     MatMult(F,u,r);

    171:     /* convergence test */
    172:     VecNorm(r,NORM_2,&resnorm);
    173:     (*nep->converged)(nep,lambda,0,resnorm,&nep->errest[nep->nconv],nep->convergedctx);
    174:     nep->eigr[nep->nconv] = lambda;
    175:     if (nep->errest[nep->nconv]<=nep->tol || nep->errest[nep->nconv]<=ctx->deftol) {
    176:       if (nep->errest[nep->nconv]<=ctx->deftol && !extop->ref && nep->nconv) {
    177:         NEPDeflationExtractEigenpair(extop,nep->nconv,u,lambda,nep->ds);
    178:         NEPDeflationSetRefine(extop,PETSC_TRUE);
    179:         MatMult(F,u,r);
    180:         VecNorm(r,NORM_2,&resnorm);
    181:         (*nep->converged)(nep,lambda,0,resnorm,&nep->errest[nep->nconv],nep->convergedctx);
    182:         if (nep->errest[nep->nconv]<=nep->tol) lock = PETSC_TRUE;
    183:       } else if (nep->errest[nep->nconv]<=nep->tol) lock = PETSC_TRUE;
    184:     }

    186:     if (lock) {
    187:       NEPDeflationSetRefine(extop,PETSC_FALSE);
    188:       nep->nconv = nep->nconv + 1;
    189:       skip = PETSC_TRUE;
    190:       lock = PETSC_FALSE;
    191:       NEPDeflationLocking(extop,u,lambda);
    192:     }
    193:     (*nep->stopping)(nep,nep->its,nep->max_it,nep->nconv,nep->nev,&nep->reason,nep->stoppingctx);
    194:     if (!skip || nep->reason>0) NEPMonitor(nep,nep->its,nep->nconv,nep->eigr,nep->eigi,nep->errest,(nep->reason>0)?nep->nconv:nep->nconv+1);

    196:     if (nep->reason == NEP_CONVERGED_ITERATING) {
    197:       if (!skip) {
    198:         /* evaluate T(lambda) and T'(lambda) */
    199:         NEPSLPSetUpLinearEP(nep,extop,lambda,u,nep->its==1?PETSC_TRUE:PETSC_FALSE);
    200:         /* compute new eigenvalue correction mu and eigenvector approximation u */
    201:         EPSSolve(ctx->eps);
    202:         EPSGetConverged(ctx->eps,&nconv);
    203:         if (!nconv) {
    204:           PetscInfo(nep,"iter=%" PetscInt_FMT ", inner iteration failed, stopping solve\n",nep->its);
    205:           nep->reason = NEP_DIVERGED_LINEAR_SOLVE;
    206:           break;
    207:         }
    208:         EPSGetEigenpair(ctx->eps,0,&mu,&im,u,NULL);
    209:         mu = 1.0/mu;
    211:       } else {
    212:         nep->its--;  /* do not count this as a full iteration */
    213:         /* use second eigenpair computed in previous iteration */
    214:         EPSGetConverged(ctx->eps,&nconv);
    215:         if (nconv>=2) {
    216:           EPSGetEigenpair(ctx->eps,1,&mu,&im,u,NULL);
    217:           mu = 1.0/mu;
    218:         } else {
    219:           NEPDeflationSetRandomVec(extop,u);
    220:           mu = lambda-sigma;
    221:         }
    222:         skip = PETSC_FALSE;
    223:       }
    224:       /* correct eigenvalue */
    225:       lambda = lambda - mu;
    226:     }
    227:   }
    228:   NEPDeflationGetInvariantPair(extop,NULL,&H);
    229:   MatGetSize(H,NULL,&ldh);
    230:   DSReset(nep->ds);
    231:   DSSetType(nep->ds,DSNHEP);
    232:   DSAllocate(nep->ds,PetscMax(nep->nconv,1));
    233:   DSGetLeadingDimension(nep->ds,&ldds);
    234:   MatDenseGetArrayRead(H,&Hp);
    235:   DSGetArray(nep->ds,DS_MAT_A,&Ap);
    236:   for (j=0;j<nep->nconv;j++)
    237:     for (i=0;i<nep->nconv;i++) Ap[j*ldds+i] = Hp[j*ldh+i];
    238:   DSRestoreArray(nep->ds,DS_MAT_A,&Ap);
    239:   MatDenseRestoreArrayRead(H,&Hp);
    240:   MatDestroy(&H);
    241:   DSSetDimensions(nep->ds,nep->nconv,0,nep->nconv);
    242:   DSSolve(nep->ds,nep->eigr,nep->eigi);
    243:   NEPDeflationReset(extop);
    244:   VecDestroy(&u);
    245:   VecDestroy(&r);
    246:   PetscFunctionReturn(0);
    247: }

    249: PetscErrorCode NEPSetFromOptions_SLP(PetscOptionItems *PetscOptionsObject,NEP nep)
    250: {
    251:   NEP_SLP        *ctx = (NEP_SLP*)nep->data;
    252:   PetscBool      flg;
    253:   PetscReal      r;

    255:   PetscOptionsHead(PetscOptionsObject,"NEP SLP Options");

    257:     r = 0.0;
    258:     PetscOptionsReal("-nep_slp_deflation_threshold","Tolerance used as a threshold for including deflated eigenpairs","NEPSLPSetDeflationThreshold",ctx->deftol,&r,&flg);
    259:     if (flg) NEPSLPSetDeflationThreshold(nep,r);

    261:   PetscOptionsTail();

    263:   if (!ctx->eps) NEPSLPGetEPS(nep,&ctx->eps);
    264:   EPSSetFromOptions(ctx->eps);
    265:   if (nep->twosided) {
    266:     if (!ctx->epsts) NEPSLPGetEPSLeft(nep,&ctx->epsts);
    267:     EPSSetFromOptions(ctx->epsts);
    268:   }
    269:   if (!ctx->ksp) NEPSLPGetKSP(nep,&ctx->ksp);
    270:   KSPSetFromOptions(ctx->ksp);
    271:   PetscFunctionReturn(0);
    272: }

    274: static PetscErrorCode NEPSLPSetDeflationThreshold_SLP(NEP nep,PetscReal deftol)
    275: {
    276:   NEP_SLP *ctx = (NEP_SLP*)nep->data;

    278:   if (deftol == PETSC_DEFAULT) {
    279:     ctx->deftol = PETSC_DEFAULT;
    280:     nep->state  = NEP_STATE_INITIAL;
    281:   } else {
    283:     ctx->deftol = deftol;
    284:   }
    285:   PetscFunctionReturn(0);
    286: }

    288: /*@
    289:    NEPSLPSetDeflationThreshold - Sets the threshold value used to switch between
    290:    deflated and non-deflated iteration.

    292:    Logically Collective on nep

    294:    Input Parameters:
    295: +  nep    - nonlinear eigenvalue solver
    296: -  deftol - the threshold value

    298:    Options Database Keys:
    299: .  -nep_slp_deflation_threshold <deftol> - set the threshold

    301:    Notes:
    302:    Normally, the solver iterates on the extended problem in order to deflate
    303:    previously converged eigenpairs. If this threshold is set to a nonzero value,
    304:    then once the residual error is below this threshold the solver will
    305:    continue the iteration without deflation. The intention is to be able to
    306:    improve the current eigenpair further, despite having previous eigenpairs
    307:    with somewhat bad precision.

    309:    Level: advanced

    311: .seealso: NEPSLPGetDeflationThreshold()
    312: @*/
    313: PetscErrorCode NEPSLPSetDeflationThreshold(NEP nep,PetscReal deftol)
    314: {
    317:   PetscTryMethod(nep,"NEPSLPSetDeflationThreshold_C",(NEP,PetscReal),(nep,deftol));
    318:   PetscFunctionReturn(0);
    319: }

    321: static PetscErrorCode NEPSLPGetDeflationThreshold_SLP(NEP nep,PetscReal *deftol)
    322: {
    323:   NEP_SLP *ctx = (NEP_SLP*)nep->data;

    325:   *deftol = ctx->deftol;
    326:   PetscFunctionReturn(0);
    327: }

    329: /*@
    330:    NEPSLPGetDeflationThreshold - Returns the threshold value that controls deflation.

    332:    Not Collective

    334:    Input Parameter:
    335: .  nep - nonlinear eigenvalue solver

    337:    Output Parameter:
    338: .  deftol - the threshold

    340:    Level: advanced

    342: .seealso: NEPSLPSetDeflationThreshold()
    343: @*/
    344: PetscErrorCode NEPSLPGetDeflationThreshold(NEP nep,PetscReal *deftol)
    345: {
    348:   PetscUseMethod(nep,"NEPSLPGetDeflationThreshold_C",(NEP,PetscReal*),(nep,deftol));
    349:   PetscFunctionReturn(0);
    350: }

    352: static PetscErrorCode NEPSLPSetEPS_SLP(NEP nep,EPS eps)
    353: {
    354:   NEP_SLP        *ctx = (NEP_SLP*)nep->data;

    356:   PetscObjectReference((PetscObject)eps);
    357:   EPSDestroy(&ctx->eps);
    358:   ctx->eps = eps;
    359:   PetscLogObjectParent((PetscObject)nep,(PetscObject)ctx->eps);
    360:   nep->state = NEP_STATE_INITIAL;
    361:   PetscFunctionReturn(0);
    362: }

    364: /*@
    365:    NEPSLPSetEPS - Associate a linear eigensolver object (EPS) to the
    366:    nonlinear eigenvalue solver.

    368:    Collective on nep

    370:    Input Parameters:
    371: +  nep - nonlinear eigenvalue solver
    372: -  eps - the eigensolver object

    374:    Level: advanced

    376: .seealso: NEPSLPGetEPS()
    377: @*/
    378: PetscErrorCode NEPSLPSetEPS(NEP nep,EPS eps)
    379: {
    383:   PetscTryMethod(nep,"NEPSLPSetEPS_C",(NEP,EPS),(nep,eps));
    384:   PetscFunctionReturn(0);
    385: }

    387: static PetscErrorCode NEPSLPGetEPS_SLP(NEP nep,EPS *eps)
    388: {
    389:   NEP_SLP        *ctx = (NEP_SLP*)nep->data;

    391:   if (!ctx->eps) {
    392:     EPSCreate(PetscObjectComm((PetscObject)nep),&ctx->eps);
    393:     PetscObjectIncrementTabLevel((PetscObject)ctx->eps,(PetscObject)nep,1);
    394:     EPSSetOptionsPrefix(ctx->eps,((PetscObject)nep)->prefix);
    395:     EPSAppendOptionsPrefix(ctx->eps,"nep_slp_");
    396:     PetscLogObjectParent((PetscObject)nep,(PetscObject)ctx->eps);
    397:     PetscObjectSetOptions((PetscObject)ctx->eps,((PetscObject)nep)->options);
    398:   }
    399:   *eps = ctx->eps;
    400:   PetscFunctionReturn(0);
    401: }

    403: /*@
    404:    NEPSLPGetEPS - Retrieve the linear eigensolver object (EPS) associated
    405:    to the nonlinear eigenvalue solver.

    407:    Not Collective

    409:    Input Parameter:
    410: .  nep - nonlinear eigenvalue solver

    412:    Output Parameter:
    413: .  eps - the eigensolver object

    415:    Level: advanced

    417: .seealso: NEPSLPSetEPS()
    418: @*/
    419: PetscErrorCode NEPSLPGetEPS(NEP nep,EPS *eps)
    420: {
    423:   PetscUseMethod(nep,"NEPSLPGetEPS_C",(NEP,EPS*),(nep,eps));
    424:   PetscFunctionReturn(0);
    425: }

    427: static PetscErrorCode NEPSLPSetEPSLeft_SLP(NEP nep,EPS eps)
    428: {
    429:   NEP_SLP        *ctx = (NEP_SLP*)nep->data;

    431:   PetscObjectReference((PetscObject)eps);
    432:   EPSDestroy(&ctx->epsts);
    433:   ctx->epsts = eps;
    434:   PetscLogObjectParent((PetscObject)nep,(PetscObject)ctx->epsts);
    435:   nep->state = NEP_STATE_INITIAL;
    436:   PetscFunctionReturn(0);
    437: }

    439: /*@
    440:    NEPSLPSetEPSLeft - Associate a linear eigensolver object (EPS) to the
    441:    nonlinear eigenvalue solver, used to compute left eigenvectors in the
    442:    two-sided variant of SLP.

    444:    Collective on nep

    446:    Input Parameters:
    447: +  nep - nonlinear eigenvalue solver
    448: -  eps - the eigensolver object

    450:    Level: advanced

    452: .seealso: NEPSLPGetEPSLeft(), NEPSetTwoSided()
    453: @*/
    454: PetscErrorCode NEPSLPSetEPSLeft(NEP nep,EPS eps)
    455: {
    459:   PetscTryMethod(nep,"NEPSLPSetEPSLeft_C",(NEP,EPS),(nep,eps));
    460:   PetscFunctionReturn(0);
    461: }

    463: static PetscErrorCode NEPSLPGetEPSLeft_SLP(NEP nep,EPS *eps)
    464: {
    465:   NEP_SLP        *ctx = (NEP_SLP*)nep->data;

    467:   if (!ctx->epsts) {
    468:     EPSCreate(PetscObjectComm((PetscObject)nep),&ctx->epsts);
    469:     PetscObjectIncrementTabLevel((PetscObject)ctx->epsts,(PetscObject)nep,1);
    470:     EPSSetOptionsPrefix(ctx->epsts,((PetscObject)nep)->prefix);
    471:     EPSAppendOptionsPrefix(ctx->epsts,"nep_slp_left_");
    472:     PetscLogObjectParent((PetscObject)nep,(PetscObject)ctx->epsts);
    473:     PetscObjectSetOptions((PetscObject)ctx->epsts,((PetscObject)nep)->options);
    474:   }
    475:   *eps = ctx->epsts;
    476:   PetscFunctionReturn(0);
    477: }

    479: /*@
    480:    NEPSLPGetEPSLeft - Retrieve the linear eigensolver object (EPS) associated
    481:    to the nonlinear eigenvalue solver, used to compute left eigenvectors in the
    482:    two-sided variant of SLP.

    484:    Not Collective

    486:    Input Parameter:
    487: .  nep - nonlinear eigenvalue solver

    489:    Output Parameter:
    490: .  eps - the eigensolver object

    492:    Level: advanced

    494: .seealso: NEPSLPSetEPSLeft(), NEPSetTwoSided()
    495: @*/
    496: PetscErrorCode NEPSLPGetEPSLeft(NEP nep,EPS *eps)
    497: {
    500:   PetscUseMethod(nep,"NEPSLPGetEPSLeft_C",(NEP,EPS*),(nep,eps));
    501:   PetscFunctionReturn(0);
    502: }

    504: static PetscErrorCode NEPSLPSetKSP_SLP(NEP nep,KSP ksp)
    505: {
    506:   NEP_SLP        *ctx = (NEP_SLP*)nep->data;

    508:   PetscObjectReference((PetscObject)ksp);
    509:   KSPDestroy(&ctx->ksp);
    510:   ctx->ksp = ksp;
    511:   PetscLogObjectParent((PetscObject)nep,(PetscObject)ctx->ksp);
    512:   nep->state = NEP_STATE_INITIAL;
    513:   PetscFunctionReturn(0);
    514: }

    516: /*@
    517:    NEPSLPSetKSP - Associate a linear solver object (KSP) to the nonlinear
    518:    eigenvalue solver.

    520:    Collective on nep

    522:    Input Parameters:
    523: +  nep - eigenvalue solver
    524: -  ksp - the linear solver object

    526:    Level: advanced

    528: .seealso: NEPSLPGetKSP()
    529: @*/
    530: PetscErrorCode NEPSLPSetKSP(NEP nep,KSP ksp)
    531: {
    535:   PetscTryMethod(nep,"NEPSLPSetKSP_C",(NEP,KSP),(nep,ksp));
    536:   PetscFunctionReturn(0);
    537: }

    539: static PetscErrorCode NEPSLPGetKSP_SLP(NEP nep,KSP *ksp)
    540: {
    541:   NEP_SLP        *ctx = (NEP_SLP*)nep->data;

    543:   if (!ctx->ksp) {
    544:     KSPCreate(PetscObjectComm((PetscObject)nep),&ctx->ksp);
    545:     PetscObjectIncrementTabLevel((PetscObject)ctx->ksp,(PetscObject)nep,1);
    546:     KSPSetOptionsPrefix(ctx->ksp,((PetscObject)nep)->prefix);
    547:     KSPAppendOptionsPrefix(ctx->ksp,"nep_slp_");
    548:     PetscLogObjectParent((PetscObject)nep,(PetscObject)ctx->ksp);
    549:     PetscObjectSetOptions((PetscObject)ctx->ksp,((PetscObject)nep)->options);
    550:     KSPSetErrorIfNotConverged(ctx->ksp,PETSC_TRUE);
    551:     KSPSetTolerances(ctx->ksp,SlepcDefaultTol(nep->tol),PETSC_DEFAULT,PETSC_DEFAULT,PETSC_DEFAULT);
    552:   }
    553:   *ksp = ctx->ksp;
    554:   PetscFunctionReturn(0);
    555: }

    557: /*@
    558:    NEPSLPGetKSP - Retrieve the linear solver object (KSP) associated with
    559:    the nonlinear eigenvalue solver.

    561:    Not Collective

    563:    Input Parameter:
    564: .  nep - nonlinear eigenvalue solver

    566:    Output Parameter:
    567: .  ksp - the linear solver object

    569:    Level: advanced

    571: .seealso: NEPSLPSetKSP()
    572: @*/
    573: PetscErrorCode NEPSLPGetKSP(NEP nep,KSP *ksp)
    574: {
    577:   PetscUseMethod(nep,"NEPSLPGetKSP_C",(NEP,KSP*),(nep,ksp));
    578:   PetscFunctionReturn(0);
    579: }

    581: PetscErrorCode NEPView_SLP(NEP nep,PetscViewer viewer)
    582: {
    583:   NEP_SLP        *ctx = (NEP_SLP*)nep->data;
    584:   PetscBool      isascii;

    586:   PetscObjectTypeCompare((PetscObject)viewer,PETSCVIEWERASCII,&isascii);
    587:   if (isascii) {
    588:     if (ctx->deftol) PetscViewerASCIIPrintf(viewer,"  deflation threshold: %g\n",(double)ctx->deftol);
    589:     if (!ctx->eps) NEPSLPGetEPS(nep,&ctx->eps);
    590:     PetscViewerASCIIPushTab(viewer);
    591:     EPSView(ctx->eps,viewer);
    592:     if (nep->twosided) {
    593:       if (!ctx->epsts) NEPSLPGetEPSLeft(nep,&ctx->epsts);
    594:       EPSView(ctx->epsts,viewer);
    595:     }
    596:     if (!ctx->ksp) NEPSLPGetKSP(nep,&ctx->ksp);
    597:     KSPView(ctx->ksp,viewer);
    598:     PetscViewerASCIIPopTab(viewer);
    599:   }
    600:   PetscFunctionReturn(0);
    601: }

    603: PetscErrorCode NEPReset_SLP(NEP nep)
    604: {
    605:   NEP_SLP        *ctx = (NEP_SLP*)nep->data;

    607:   EPSReset(ctx->eps);
    608:   if (nep->twosided) EPSReset(ctx->epsts);
    609:   KSPReset(ctx->ksp);
    610:   PetscFunctionReturn(0);
    611: }

    613: PetscErrorCode NEPDestroy_SLP(NEP nep)
    614: {
    615:   NEP_SLP        *ctx = (NEP_SLP*)nep->data;

    617:   KSPDestroy(&ctx->ksp);
    618:   EPSDestroy(&ctx->eps);
    619:   EPSDestroy(&ctx->epsts);
    620:   PetscFree(nep->data);
    621:   PetscObjectComposeFunction((PetscObject)nep,"NEPSLPSetDeflationThreshold_C",NULL);
    622:   PetscObjectComposeFunction((PetscObject)nep,"NEPSLPGetDeflationThreshold_C",NULL);
    623:   PetscObjectComposeFunction((PetscObject)nep,"NEPSLPSetEPS_C",NULL);
    624:   PetscObjectComposeFunction((PetscObject)nep,"NEPSLPGetEPS_C",NULL);
    625:   PetscObjectComposeFunction((PetscObject)nep,"NEPSLPSetEPSLeft_C",NULL);
    626:   PetscObjectComposeFunction((PetscObject)nep,"NEPSLPGetEPSLeft_C",NULL);
    627:   PetscObjectComposeFunction((PetscObject)nep,"NEPSLPSetKSP_C",NULL);
    628:   PetscObjectComposeFunction((PetscObject)nep,"NEPSLPGetKSP_C",NULL);
    629:   PetscFunctionReturn(0);
    630: }

    632: SLEPC_EXTERN PetscErrorCode NEPCreate_SLP(NEP nep)
    633: {
    634:   NEP_SLP        *ctx;

    636:   PetscNewLog(nep,&ctx);
    637:   nep->data = (void*)ctx;

    639:   nep->useds  = PETSC_TRUE;
    640:   ctx->deftol = PETSC_DEFAULT;

    642:   nep->ops->solve          = NEPSolve_SLP;
    643:   nep->ops->setup          = NEPSetUp_SLP;
    644:   nep->ops->setfromoptions = NEPSetFromOptions_SLP;
    645:   nep->ops->reset          = NEPReset_SLP;
    646:   nep->ops->destroy        = NEPDestroy_SLP;
    647:   nep->ops->view           = NEPView_SLP;
    648:   nep->ops->computevectors = NEPComputeVectors_Schur;

    650:   PetscObjectComposeFunction((PetscObject)nep,"NEPSLPSetDeflationThreshold_C",NEPSLPSetDeflationThreshold_SLP);
    651:   PetscObjectComposeFunction((PetscObject)nep,"NEPSLPGetDeflationThreshold_C",NEPSLPGetDeflationThreshold_SLP);
    652:   PetscObjectComposeFunction((PetscObject)nep,"NEPSLPSetEPS_C",NEPSLPSetEPS_SLP);
    653:   PetscObjectComposeFunction((PetscObject)nep,"NEPSLPGetEPS_C",NEPSLPGetEPS_SLP);
    654:   PetscObjectComposeFunction((PetscObject)nep,"NEPSLPSetEPSLeft_C",NEPSLPSetEPSLeft_SLP);
    655:   PetscObjectComposeFunction((PetscObject)nep,"NEPSLPGetEPSLeft_C",NEPSLPGetEPSLeft_SLP);
    656:   PetscObjectComposeFunction((PetscObject)nep,"NEPSLPSetKSP_C",NEPSLPSetKSP_SLP);
    657:   PetscObjectComposeFunction((PetscObject)nep,"NEPSLPGetKSP_C",NEPSLPGetKSP_SLP);
    658:   PetscFunctionReturn(0);
    659: }