Actual source code: slp.c

slepc-3.17.0 2022-03-31
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: }