Date: 2023-01-26T12:19:28+00:00

Actual source code: slp.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:    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:   return 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:   return 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:   return 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:   return 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:   return 0;
    137: }

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

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

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

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

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

    185:     if (lock) {
    186:       NEPDeflationSetRefine(extop,PETSC_FALSE);
    187:       nep->nconv = nep->nconv + 1;
    188:       skip = PETSC_TRUE;
    189:       lock = PETSC_FALSE;
    190:       NEPDeflationLocking(extop,u,lambda);
    191:     }
    192:     (*nep->stopping)(nep,nep->its,nep->max_it,nep->nconv,nep->nev,&nep->reason,nep->stoppingctx);
    193:     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);

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

    242: PetscErrorCode NEPSetFromOptions_SLP(NEP nep,PetscOptionItems *PetscOptionsObject)
    243: {
    244:   NEP_SLP        *ctx = (NEP_SLP*)nep->data;
    245:   PetscBool      flg;
    246:   PetscReal      r;

    248:   PetscOptionsHeadBegin(PetscOptionsObject,"NEP SLP Options");

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

    254:   PetscOptionsHeadEnd();

    256:   if (!ctx->eps) NEPSLPGetEPS(nep,&ctx->eps);
    257:   EPSSetFromOptions(ctx->eps);
    258:   if (nep->twosided) {
    259:     if (!ctx->epsts) NEPSLPGetEPSLeft(nep,&ctx->epsts);
    260:     EPSSetFromOptions(ctx->epsts);
    261:   }
    262:   if (!ctx->ksp) NEPSLPGetKSP(nep,&ctx->ksp);
    263:   KSPSetFromOptions(ctx->ksp);
    264:   return 0;
    265: }

    267: static PetscErrorCode NEPSLPSetDeflationThreshold_SLP(NEP nep,PetscReal deftol)
    268: {
    269:   NEP_SLP *ctx = (NEP_SLP*)nep->data;

    271:   if (deftol == PETSC_DEFAULT) {
    272:     ctx->deftol = PETSC_DEFAULT;
    273:     nep->state  = NEP_STATE_INITIAL;
    274:   } else {
    276:     ctx->deftol = deftol;
    277:   }
    278:   return 0;
    279: }

    281: /*@
    282:    NEPSLPSetDeflationThreshold - Sets the threshold value used to switch between
    283:    deflated and non-deflated iteration.

    285:    Logically Collective on nep

    287:    Input Parameters:
    288: +  nep    - nonlinear eigenvalue solver
    289: -  deftol - the threshold value

    291:    Options Database Keys:
    292: .  -nep_slp_deflation_threshold <deftol> - set the threshold

    294:    Notes:
    295:    Normally, the solver iterates on the extended problem in order to deflate
    296:    previously converged eigenpairs. If this threshold is set to a nonzero value,
    297:    then once the residual error is below this threshold the solver will
    298:    continue the iteration without deflation. The intention is to be able to
    299:    improve the current eigenpair further, despite having previous eigenpairs
    300:    with somewhat bad precision.

    302:    Level: advanced

    304: .seealso: NEPSLPGetDeflationThreshold()
    305: @*/
    306: PetscErrorCode NEPSLPSetDeflationThreshold(NEP nep,PetscReal deftol)
    307: {
    310:   PetscTryMethod(nep,"NEPSLPSetDeflationThreshold_C",(NEP,PetscReal),(nep,deftol));
    311:   return 0;
    312: }

    314: static PetscErrorCode NEPSLPGetDeflationThreshold_SLP(NEP nep,PetscReal *deftol)
    315: {
    316:   NEP_SLP *ctx = (NEP_SLP*)nep->data;

    318:   *deftol = ctx->deftol;
    319:   return 0;
    320: }

    322: /*@
    323:    NEPSLPGetDeflationThreshold - Returns the threshold value that controls deflation.

    325:    Not Collective

    327:    Input Parameter:
    328: .  nep - nonlinear eigenvalue solver

    330:    Output Parameter:
    331: .  deftol - the threshold

    333:    Level: advanced

    335: .seealso: NEPSLPSetDeflationThreshold()
    336: @*/
    337: PetscErrorCode NEPSLPGetDeflationThreshold(NEP nep,PetscReal *deftol)
    338: {
    341:   PetscUseMethod(nep,"NEPSLPGetDeflationThreshold_C",(NEP,PetscReal*),(nep,deftol));
    342:   return 0;
    343: }

    345: static PetscErrorCode NEPSLPSetEPS_SLP(NEP nep,EPS eps)
    346: {
    347:   NEP_SLP        *ctx = (NEP_SLP*)nep->data;

    349:   PetscObjectReference((PetscObject)eps);
    350:   EPSDestroy(&ctx->eps);
    351:   ctx->eps = eps;
    352:   nep->state = NEP_STATE_INITIAL;
    353:   return 0;
    354: }

    356: /*@
    357:    NEPSLPSetEPS - Associate a linear eigensolver object (EPS) to the
    358:    nonlinear eigenvalue solver.

    360:    Collective on nep

    362:    Input Parameters:
    363: +  nep - nonlinear eigenvalue solver
    364: -  eps - the eigensolver object

    366:    Level: advanced

    368: .seealso: NEPSLPGetEPS()
    369: @*/
    370: PetscErrorCode NEPSLPSetEPS(NEP nep,EPS eps)
    371: {
    375:   PetscTryMethod(nep,"NEPSLPSetEPS_C",(NEP,EPS),(nep,eps));
    376:   return 0;
    377: }

    379: static PetscErrorCode NEPSLPGetEPS_SLP(NEP nep,EPS *eps)
    380: {
    381:   NEP_SLP        *ctx = (NEP_SLP*)nep->data;

    383:   if (!ctx->eps) {
    384:     EPSCreate(PetscObjectComm((PetscObject)nep),&ctx->eps);
    385:     PetscObjectIncrementTabLevel((PetscObject)ctx->eps,(PetscObject)nep,1);
    386:     EPSSetOptionsPrefix(ctx->eps,((PetscObject)nep)->prefix);
    387:     EPSAppendOptionsPrefix(ctx->eps,"nep_slp_");
    388:     PetscObjectSetOptions((PetscObject)ctx->eps,((PetscObject)nep)->options);
    389:   }
    390:   *eps = ctx->eps;
    391:   return 0;
    392: }

    394: /*@
    395:    NEPSLPGetEPS - Retrieve the linear eigensolver object (EPS) associated
    396:    to the nonlinear eigenvalue solver.

    398:    Not Collective

    400:    Input Parameter:
    401: .  nep - nonlinear eigenvalue solver

    403:    Output Parameter:
    404: .  eps - the eigensolver object

    406:    Level: advanced

    408: .seealso: NEPSLPSetEPS()
    409: @*/
    410: PetscErrorCode NEPSLPGetEPS(NEP nep,EPS *eps)
    411: {
    414:   PetscUseMethod(nep,"NEPSLPGetEPS_C",(NEP,EPS*),(nep,eps));
    415:   return 0;
    416: }

    418: static PetscErrorCode NEPSLPSetEPSLeft_SLP(NEP nep,EPS eps)
    419: {
    420:   NEP_SLP        *ctx = (NEP_SLP*)nep->data;

    422:   PetscObjectReference((PetscObject)eps);
    423:   EPSDestroy(&ctx->epsts);
    424:   ctx->epsts = eps;
    425:   nep->state = NEP_STATE_INITIAL;
    426:   return 0;
    427: }

    429: /*@
    430:    NEPSLPSetEPSLeft - Associate a linear eigensolver object (EPS) to the
    431:    nonlinear eigenvalue solver, used to compute left eigenvectors in the
    432:    two-sided variant of SLP.

    434:    Collective on nep

    436:    Input Parameters:
    437: +  nep - nonlinear eigenvalue solver
    438: -  eps - the eigensolver object

    440:    Level: advanced

    442: .seealso: NEPSLPGetEPSLeft(), NEPSetTwoSided()
    443: @*/
    444: PetscErrorCode NEPSLPSetEPSLeft(NEP nep,EPS eps)
    445: {
    449:   PetscTryMethod(nep,"NEPSLPSetEPSLeft_C",(NEP,EPS),(nep,eps));
    450:   return 0;
    451: }

    453: static PetscErrorCode NEPSLPGetEPSLeft_SLP(NEP nep,EPS *eps)
    454: {
    455:   NEP_SLP        *ctx = (NEP_SLP*)nep->data;

    457:   if (!ctx->epsts) {
    458:     EPSCreate(PetscObjectComm((PetscObject)nep),&ctx->epsts);
    459:     PetscObjectIncrementTabLevel((PetscObject)ctx->epsts,(PetscObject)nep,1);
    460:     EPSSetOptionsPrefix(ctx->epsts,((PetscObject)nep)->prefix);
    461:     EPSAppendOptionsPrefix(ctx->epsts,"nep_slp_left_");
    462:     PetscObjectSetOptions((PetscObject)ctx->epsts,((PetscObject)nep)->options);
    463:   }
    464:   *eps = ctx->epsts;
    465:   return 0;
    466: }

    468: /*@
    469:    NEPSLPGetEPSLeft - Retrieve the linear eigensolver object (EPS) associated
    470:    to the nonlinear eigenvalue solver, used to compute left eigenvectors in the
    471:    two-sided variant of SLP.

    473:    Not Collective

    475:    Input Parameter:
    476: .  nep - nonlinear eigenvalue solver

    478:    Output Parameter:
    479: .  eps - the eigensolver object

    481:    Level: advanced

    483: .seealso: NEPSLPSetEPSLeft(), NEPSetTwoSided()
    484: @*/
    485: PetscErrorCode NEPSLPGetEPSLeft(NEP nep,EPS *eps)
    486: {
    489:   PetscUseMethod(nep,"NEPSLPGetEPSLeft_C",(NEP,EPS*),(nep,eps));
    490:   return 0;
    491: }

    493: static PetscErrorCode NEPSLPSetKSP_SLP(NEP nep,KSP ksp)
    494: {
    495:   NEP_SLP        *ctx = (NEP_SLP*)nep->data;

    497:   PetscObjectReference((PetscObject)ksp);
    498:   KSPDestroy(&ctx->ksp);
    499:   ctx->ksp   = ksp;
    500:   nep->state = NEP_STATE_INITIAL;
    501:   return 0;
    502: }

    504: /*@
    505:    NEPSLPSetKSP - Associate a linear solver object (KSP) to the nonlinear
    506:    eigenvalue solver.

    508:    Collective on nep

    510:    Input Parameters:
    511: +  nep - eigenvalue solver
    512: -  ksp - the linear solver object

    514:    Level: advanced

    516: .seealso: NEPSLPGetKSP()
    517: @*/
    518: PetscErrorCode NEPSLPSetKSP(NEP nep,KSP ksp)
    519: {
    523:   PetscTryMethod(nep,"NEPSLPSetKSP_C",(NEP,KSP),(nep,ksp));
    524:   return 0;
    525: }

    527: static PetscErrorCode NEPSLPGetKSP_SLP(NEP nep,KSP *ksp)
    528: {
    529:   NEP_SLP        *ctx = (NEP_SLP*)nep->data;

    531:   if (!ctx->ksp) {
    532:     KSPCreate(PetscObjectComm((PetscObject)nep),&ctx->ksp);
    533:     PetscObjectIncrementTabLevel((PetscObject)ctx->ksp,(PetscObject)nep,1);
    534:     KSPSetOptionsPrefix(ctx->ksp,((PetscObject)nep)->prefix);
    535:     KSPAppendOptionsPrefix(ctx->ksp,"nep_slp_");
    536:     PetscObjectSetOptions((PetscObject)ctx->ksp,((PetscObject)nep)->options);
    537:     KSPSetErrorIfNotConverged(ctx->ksp,PETSC_TRUE);
    538:     KSPSetTolerances(ctx->ksp,SlepcDefaultTol(nep->tol),PETSC_DEFAULT,PETSC_DEFAULT,PETSC_DEFAULT);
    539:   }
    540:   *ksp = ctx->ksp;
    541:   return 0;
    542: }

    544: /*@
    545:    NEPSLPGetKSP - Retrieve the linear solver object (KSP) associated with
    546:    the nonlinear eigenvalue solver.

    548:    Not Collective

    550:    Input Parameter:
    551: .  nep - nonlinear eigenvalue solver

    553:    Output Parameter:
    554: .  ksp - the linear solver object

    556:    Level: advanced

    558: .seealso: NEPSLPSetKSP()
    559: @*/
    560: PetscErrorCode NEPSLPGetKSP(NEP nep,KSP *ksp)
    561: {
    564:   PetscUseMethod(nep,"NEPSLPGetKSP_C",(NEP,KSP*),(nep,ksp));
    565:   return 0;
    566: }

    568: PetscErrorCode NEPView_SLP(NEP nep,PetscViewer viewer)
    569: {
    570:   NEP_SLP        *ctx = (NEP_SLP*)nep->data;
    571:   PetscBool      isascii;

    573:   PetscObjectTypeCompare((PetscObject)viewer,PETSCVIEWERASCII,&isascii);
    574:   if (isascii) {
    575:     if (ctx->deftol) PetscViewerASCIIPrintf(viewer,"  deflation threshold: %g\n",(double)ctx->deftol);
    576:     if (!ctx->eps) NEPSLPGetEPS(nep,&ctx->eps);
    577:     PetscViewerASCIIPushTab(viewer);
    578:     EPSView(ctx->eps,viewer);
    579:     if (nep->twosided) {
    580:       if (!ctx->epsts) NEPSLPGetEPSLeft(nep,&ctx->epsts);
    581:       EPSView(ctx->epsts,viewer);
    582:     }
    583:     if (!ctx->ksp) NEPSLPGetKSP(nep,&ctx->ksp);
    584:     KSPView(ctx->ksp,viewer);
    585:     PetscViewerASCIIPopTab(viewer);
    586:   }
    587:   return 0;
    588: }

    590: PetscErrorCode NEPReset_SLP(NEP nep)
    591: {
    592:   NEP_SLP        *ctx = (NEP_SLP*)nep->data;

    594:   EPSReset(ctx->eps);
    595:   if (nep->twosided) EPSReset(ctx->epsts);
    596:   KSPReset(ctx->ksp);
    597:   return 0;
    598: }

    600: PetscErrorCode NEPDestroy_SLP(NEP nep)
    601: {
    602:   NEP_SLP        *ctx = (NEP_SLP*)nep->data;

    604:   KSPDestroy(&ctx->ksp);
    605:   EPSDestroy(&ctx->eps);
    606:   EPSDestroy(&ctx->epsts);
    607:   PetscFree(nep->data);
    608:   PetscObjectComposeFunction((PetscObject)nep,"NEPSLPSetDeflationThreshold_C",NULL);
    609:   PetscObjectComposeFunction((PetscObject)nep,"NEPSLPGetDeflationThreshold_C",NULL);
    610:   PetscObjectComposeFunction((PetscObject)nep,"NEPSLPSetEPS_C",NULL);
    611:   PetscObjectComposeFunction((PetscObject)nep,"NEPSLPGetEPS_C",NULL);
    612:   PetscObjectComposeFunction((PetscObject)nep,"NEPSLPSetEPSLeft_C",NULL);
    613:   PetscObjectComposeFunction((PetscObject)nep,"NEPSLPGetEPSLeft_C",NULL);
    614:   PetscObjectComposeFunction((PetscObject)nep,"NEPSLPSetKSP_C",NULL);
    615:   PetscObjectComposeFunction((PetscObject)nep,"NEPSLPGetKSP_C",NULL);
    616:   return 0;
    617: }

    619: SLEPC_EXTERN PetscErrorCode NEPCreate_SLP(NEP nep)
    620: {
    621:   NEP_SLP        *ctx;

    623:   PetscNew(&ctx);
    624:   nep->data = (void*)ctx;

    626:   nep->useds  = PETSC_TRUE;
    627:   ctx->deftol = PETSC_DEFAULT;

    629:   nep->ops->solve          = NEPSolve_SLP;
    630:   nep->ops->setup          = NEPSetUp_SLP;
    631:   nep->ops->setfromoptions = NEPSetFromOptions_SLP;
    632:   nep->ops->reset          = NEPReset_SLP;
    633:   nep->ops->destroy        = NEPDestroy_SLP;
    634:   nep->ops->view           = NEPView_SLP;
    635:   nep->ops->computevectors = NEPComputeVectors_Schur;

    637:   PetscObjectComposeFunction((PetscObject)nep,"NEPSLPSetDeflationThreshold_C",NEPSLPSetDeflationThreshold_SLP);
    638:   PetscObjectComposeFunction((PetscObject)nep,"NEPSLPGetDeflationThreshold_C",NEPSLPGetDeflationThreshold_SLP);
    639:   PetscObjectComposeFunction((PetscObject)nep,"NEPSLPSetEPS_C",NEPSLPSetEPS_SLP);
    640:   PetscObjectComposeFunction((PetscObject)nep,"NEPSLPGetEPS_C",NEPSLPGetEPS_SLP);
    641:   PetscObjectComposeFunction((PetscObject)nep,"NEPSLPSetEPSLeft_C",NEPSLPSetEPSLeft_SLP);
    642:   PetscObjectComposeFunction((PetscObject)nep,"NEPSLPGetEPSLeft_C",NEPSLPGetEPSLeft_SLP);
    643:   PetscObjectComposeFunction((PetscObject)nep,"NEPSLPSetKSP_C",NEPSLPSetKSP_SLP);
    644:   PetscObjectComposeFunction((PetscObject)nep,"NEPSLPGetKSP_C",NEPSLPGetKSP_SLP);
    645:   return 0;
    646: }