Actual source code: slp.c

slepc-3.13.2 2020-05-12
Report Typos and Errors
  1: /*
  2:    - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
  3:    SLEPc - Scalable Library for Eigenvalue Problem Computations
  4:    Copyright (c) 2002-2020, 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: Succesive 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: {
 37:   NEP_SLP        *ctx = (NEP_SLP*)nep->data;
 38:   PetscBool      istrivial,flg;
 39:   ST             st;

 42:   if (nep->ncv) { PetscInfo(nep,"Setting ncv = nev, ignoring user-provided value\n"); }
 43:   nep->ncv = nep->nev;
 44:   if (nep->mpd) { PetscInfo(nep,"Setting mpd = nev, ignoring user-provided value\n"); }
 45:   nep->mpd = nep->nev;
 46:   if (nep->ncv>nep->nev+nep->mpd) SETERRQ(PetscObjectComm((PetscObject)nep),1,"The value of ncv must not be larger than nev+mpd");
 47:   if (!nep->max_it) nep->max_it = PetscMax(5000,2*nep->n/nep->ncv);
 48:   if (nep->which && nep->which!=NEP_TARGET_MAGNITUDE) SETERRQ(PetscObjectComm((PetscObject)nep),1,"Wrong value of which");

 50:   RGIsTrivial(nep->rg,&istrivial);
 51:   if (!istrivial) SETERRQ(PetscObjectComm((PetscObject)nep),PETSC_ERR_SUP,"This solver does not support region filtering");

 53:   if (!ctx->eps) { NEPSLPGetEPS(nep,&ctx->eps); }
 54:   EPSGetST(ctx->eps,&st);
 55:   PetscObjectTypeCompareAny((PetscObject)st,&flg,STSINVERT,STCAYLEY,"");
 56:   if (flg) SETERRQ(PetscObjectComm((PetscObject)nep),1,"SLP does not support spectral transformation");
 57:   EPSSetDimensions(ctx->eps,1,PETSC_DECIDE,PETSC_DECIDE);
 58:   EPSSetWhichEigenpairs(ctx->eps,EPS_LARGEST_MAGNITUDE);
 59:   EPSSetTolerances(ctx->eps,nep->tol==PETSC_DEFAULT?SLEPC_DEFAULT_TOL/10.0:nep->tol/10.0,nep->max_it?nep->max_it:PETSC_DEFAULT);
 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,"");
 66:     if (flg) SETERRQ(PetscObjectComm((PetscObject)nep),1,"SLP does not support spectral transformation");
 67:     EPSSetDimensions(ctx->epsts,1,PETSC_DECIDE,PETSC_DECIDE);
 68:     EPSSetWhichEigenpairs(ctx->epsts,EPS_LARGEST_MAGNITUDE);
 69:     EPSSetTolerances(ctx->epsts,nep->tol==PETSC_DEFAULT?SLEPC_DEFAULT_TOL/10.0:nep->tol/10.0,nep->max_it?nep->max_it:PETSC_DEFAULT);
 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:   PetscErrorCode   ierr;
 81:   NEP_SLP_MATSHELL *ctx;

 84:   MatShellGetContext(M,(void**)&ctx);
 85:   MatMult(ctx->extop->MJ,x,ctx->w);
 86:   NEPDeflationFunctionSolve(ctx->extop,ctx->w,y);
 87:   return(0);
 88: }

 90: static PetscErrorCode MatDestroy_SLP(Mat M)
 91: {
 92:   PetscErrorCode   ierr;
 93:   NEP_SLP_MATSHELL *ctx;

 96:   MatShellGetContext(M,(void**)&ctx);
 97:   VecDestroy(&ctx->w);
 98:   PetscFree(ctx);
 99:   return(0);
100: }

102: #if defined(PETSC_HAVE_CUDA)
103: static PetscErrorCode MatCreateVecs_SLP(Mat M,Vec *left,Vec *right)
104: {
105:   PetscErrorCode   ierr;
106:   NEP_SLP_MATSHELL *ctx;

109:   MatShellGetContext(M,(void**)&ctx);
110:   if (right) {
111:     VecDuplicate(ctx->w,right);
112:   }
113:   if (left) {
114:     VecDuplicate(ctx->w,left);
115:   }
116:   return(0);
117: }
118: #endif

120: static PetscErrorCode NEPSLPSetUpLinearEP(NEP nep,NEP_EXT_OP extop,PetscScalar lambda,Vec u,PetscBool ini)
121: {
122:   PetscErrorCode   ierr;
123:   NEP_SLP          *slpctx = (NEP_SLP*)nep->data;
124:   Mat              Mshell;
125:   PetscInt         nloc,mloc;
126:   NEP_SLP_MATSHELL *shellctx;

129:   if (ini) {
130:     /* Create mat shell */
131:     PetscNew(&shellctx);
132:     shellctx->extop = extop;
133:     NEPDeflationCreateVec(extop,&shellctx->w);
134:     MatGetLocalSize(nep->function,&mloc,&nloc);
135:     nloc += extop->szd; mloc += extop->szd;
136:     MatCreateShell(PetscObjectComm((PetscObject)nep),nloc,mloc,PETSC_DETERMINE,PETSC_DETERMINE,shellctx,&Mshell);
137:     MatShellSetOperation(Mshell,MATOP_MULT,(void(*)(void))MatMult_SLP);
138:     MatShellSetOperation(Mshell,MATOP_DESTROY,(void(*)(void))MatDestroy_SLP);
139: #if defined(PETSC_HAVE_CUDA)
140:     MatShellSetOperation(Mshell,MATOP_CREATE_VECS,(void(*)(void))MatCreateVecs_SLP);
141: #endif
142:     EPSSetOperators(slpctx->eps,Mshell,NULL);
143:     MatDestroy(&Mshell);
144:   }
145:   NEPDeflationSolveSetUp(extop,lambda);
146:   NEPDeflationComputeJacobian(extop,lambda,NULL);
147:   EPSSetInitialSpace(slpctx->eps,1,&u);
148:   return(0);
149: }

151: PetscErrorCode NEPSolve_SLP(NEP nep)
152: {
154:   NEP_SLP        *ctx = (NEP_SLP*)nep->data;
155:   Mat            F,H;
156:   Vec            uu,u,r;
157:   PetscScalar    sigma,lambda,mu,im,*Hp,*Ap;
158:   PetscReal      resnorm;
159:   PetscInt       nconv,ldh,ldds,i,j;
160:   PetscBool      skip=PETSC_FALSE,lock=PETSC_FALSE;
161:   NEP_EXT_OP     extop=NULL;    /* Extended operator for deflation */

164:   /* get initial approximation of eigenvalue and eigenvector */
165:   NEPGetDefaultShift(nep,&sigma);
166:   if (!nep->nini) {
167:     BVSetRandomColumn(nep->V,0);
168:   }
169:   lambda = sigma;
170:   if (!ctx->ksp) { NEPSLPGetKSP(nep,&ctx->ksp); }
171:   NEPDeflationInitialize(nep,nep->V,ctx->ksp,PETSC_TRUE,nep->nev,&extop);
172:   NEPDeflationCreateVec(extop,&u);
173:   VecDuplicate(u,&r);
174:   BVGetColumn(nep->V,0,&uu);
175:   NEPDeflationCopyToExtendedVec(extop,uu,NULL,u,PETSC_FALSE);
176:   BVRestoreColumn(nep->V,0,&uu);

178:   /* Restart loop */
179:   while (nep->reason == NEP_CONVERGED_ITERATING) {
180:     nep->its++;

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

186:     /* convergence test */
187:     VecNorm(r,NORM_2,&resnorm);
188:     (*nep->converged)(nep,lambda,0,resnorm,&nep->errest[nep->nconv],nep->convergedctx);
189:     nep->eigr[nep->nconv] = lambda;
190:     if (nep->errest[nep->nconv]<=nep->tol || nep->errest[nep->nconv]<=ctx->deftol) {
191:       if (nep->errest[nep->nconv]<=ctx->deftol && !extop->ref && nep->nconv) {
192:         NEPDeflationExtractEigenpair(extop,nep->nconv,u,lambda,nep->ds);
193:         NEPDeflationSetRefine(extop,PETSC_TRUE);
194:         MatMult(F,u,r);
195:         VecNorm(r,NORM_2,&resnorm);
196:         (*nep->converged)(nep,lambda,0,resnorm,&nep->errest[nep->nconv],nep->convergedctx);
197:         if (nep->errest[nep->nconv]<=nep->tol) lock = PETSC_TRUE;
198:       } else if (nep->errest[nep->nconv]<=nep->tol) lock = PETSC_TRUE;
199:     }

201:     if (lock) {
202:       NEPDeflationSetRefine(extop,PETSC_FALSE);
203:       nep->nconv = nep->nconv + 1;
204:       skip = PETSC_TRUE;
205:       lock = PETSC_FALSE;
206:       NEPDeflationLocking(extop,u,lambda);
207:     }
208:     (*nep->stopping)(nep,nep->its,nep->max_it,nep->nconv,nep->nev,&nep->reason,nep->stoppingctx);
209:     if (!skip || nep->reason>0) {
210:       NEPMonitor(nep,nep->its,nep->nconv,nep->eigr,nep->eigi,nep->errest,(nep->reason>0)?nep->nconv:nep->nconv+1);
211:     }

213:     if (nep->reason == NEP_CONVERGED_ITERATING) {
214:       if (!skip) {
215:         /* evaluate T(lambda) and T'(lambda) */
216:         NEPSLPSetUpLinearEP(nep,extop,lambda,u,nep->its==1?PETSC_TRUE:PETSC_FALSE);
217:         /* compute new eigenvalue correction mu and eigenvector approximation u */
218:         EPSSolve(ctx->eps);
219:         EPSGetConverged(ctx->eps,&nconv);
220:         if (!nconv) {
221:           PetscInfo1(nep,"iter=%D, inner iteration failed, stopping solve\n",nep->its);
222:           nep->reason = NEP_DIVERGED_LINEAR_SOLVE;
223:           break;
224:         }
225:         EPSGetEigenpair(ctx->eps,0,&mu,&im,u,NULL);
226:         mu = 1.0/mu;
227:         if (PetscAbsScalar(im)>PETSC_MACHINE_EPSILON) SETERRQ(PetscObjectComm((PetscObject)nep),1,"Complex eigenvalue approximation - not implemented in real scalars");
228:       } else {
229:         nep->its--;  /* do not count this as a full iteration */
230:         /* use second eigenpair computed in previous iteration */
231:         EPSGetConverged(ctx->eps,&nconv);
232:         if (nconv>=2) {
233:           EPSGetEigenpair(ctx->eps,1,&mu,&im,u,NULL);
234:           mu = 1.0/mu;
235:         } else {
236:           NEPDeflationSetRandomVec(extop,u);
237:           mu = lambda-sigma;
238:         }
239:         skip = PETSC_FALSE;
240:       }
241:       /* correct eigenvalue */
242:       lambda = lambda - mu;
243:     }
244:   }
245:   NEPDeflationGetInvariantPair(extop,NULL,&H);
246:   MatGetSize(H,NULL,&ldh);
247:   DSReset(nep->ds);
248:   DSSetType(nep->ds,DSNHEP);
249:   DSAllocate(nep->ds,PetscMax(nep->nconv,1));
250:   DSGetLeadingDimension(nep->ds,&ldds);
251:   MatDenseGetArray(H,&Hp);
252:   DSGetArray(nep->ds,DS_MAT_A,&Ap);
253:   for (j=0;j<nep->nconv;j++)
254:     for (i=0;i<nep->nconv;i++) Ap[j*ldds+i] = Hp[j*ldh+i];
255:   DSRestoreArray(nep->ds,DS_MAT_A,&Ap);
256:   MatDenseRestoreArray(H,&Hp);
257:   MatDestroy(&H);
258:   DSSetDimensions(nep->ds,nep->nconv,0,0,nep->nconv);
259:   DSSolve(nep->ds,nep->eigr,nep->eigi);
260:   NEPDeflationReset(extop);
261:   VecDestroy(&u);
262:   VecDestroy(&r);
263:   return(0);
264: }

266: PetscErrorCode NEPSetFromOptions_SLP(PetscOptionItems *PetscOptionsObject,NEP nep)
267: {
269:   NEP_SLP        *ctx = (NEP_SLP*)nep->data;
270:   PetscBool      flg;
271:   PetscReal      r;

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

276:     r = 0.0;
277:     PetscOptionsReal("-nep_slp_deflation_threshold","Tolerance used as a threshold for including deflated eigenpairs","NEPSLPSetDeflationThreshold",ctx->deftol,&r,&flg);
278:     if (flg) { NEPSLPSetDeflationThreshold(nep,r); }

280:   PetscOptionsTail();

282:   if (!ctx->eps) { NEPSLPGetEPS(nep,&ctx->eps); }
283:   EPSSetFromOptions(ctx->eps);
284:   if (nep->twosided) {
285:     if (!ctx->epsts) { NEPSLPGetEPSLeft(nep,&ctx->epsts); }
286:     EPSSetFromOptions(ctx->epsts);
287:   }
288:   if (!ctx->ksp) { NEPSLPGetKSP(nep,&ctx->ksp); }
289:   KSPSetFromOptions(ctx->ksp);
290:   return(0);
291: }

293: static PetscErrorCode NEPSLPSetDeflationThreshold_SLP(NEP nep,PetscReal deftol)
294: {
295:   NEP_SLP *ctx = (NEP_SLP*)nep->data;

298:   ctx->deftol = deftol;
299:   return(0);
300: }

302: /*@
303:    NEPSLPSetDeflationThreshold - Sets the threshold value used to switch between
304:    deflated and non-deflated iteration.

306:    Logically Collective on nep

308:    Input Parameters:
309: +  nep    - nonlinear eigenvalue solver
310: -  deftol - the threshold value

312:    Options Database Keys:
313: .  -nep_slp_deflation_threshold <deftol> - set the threshold

315:    Notes:
316:    Normally, the solver iterates on the extended problem in order to deflate
317:    previously converged eigenpairs. If this threshold is set to a nonzero value,
318:    then once the residual error is below this threshold the solver will
319:    continue the iteration without deflation. The intention is to be able to
320:    improve the current eigenpair further, despite having previous eigenpairs
321:    with somewhat bad precision.

323:    Level: advanced

325: .seealso: NEPSLPGetDeflationThreshold()
326: @*/
327: PetscErrorCode NEPSLPSetDeflationThreshold(NEP nep,PetscReal deftol)
328: {

334:   PetscTryMethod(nep,"NEPSLPSetDeflationThreshold_C",(NEP,PetscReal),(nep,deftol));
335:   return(0);
336: }

338: static PetscErrorCode NEPSLPGetDeflationThreshold_SLP(NEP nep,PetscReal *deftol)
339: {
340:   NEP_SLP *ctx = (NEP_SLP*)nep->data;

343:   *deftol = ctx->deftol;
344:   return(0);
345: }

347: /*@
348:    NEPSLPGetDeflationThreshold - Returns the threshold value that controls deflation.

350:    Not Collective

352:    Input Parameter:
353: .  nep - nonlinear eigenvalue solver

355:    Output Parameter:
356: .  deftol - the threshold

358:    Level: advanced

360: .seealso: NEPSLPSetDeflationThreshold()
361: @*/
362: PetscErrorCode NEPSLPGetDeflationThreshold(NEP nep,PetscReal *deftol)
363: {

369:   PetscUseMethod(nep,"NEPSLPGetDeflationThreshold_C",(NEP,PetscReal*),(nep,deftol));
370:   return(0);
371: }

373: static PetscErrorCode NEPSLPSetEPS_SLP(NEP nep,EPS eps)
374: {
376:   NEP_SLP        *ctx = (NEP_SLP*)nep->data;

379:   PetscObjectReference((PetscObject)eps);
380:   EPSDestroy(&ctx->eps);
381:   ctx->eps = eps;
382:   PetscLogObjectParent((PetscObject)nep,(PetscObject)ctx->eps);
383:   nep->state = NEP_STATE_INITIAL;
384:   return(0);
385: }

387: /*@
388:    NEPSLPSetEPS - Associate a linear eigensolver object (EPS) to the
389:    nonlinear eigenvalue solver.

391:    Collective on nep

393:    Input Parameters:
394: +  nep - nonlinear eigenvalue solver
395: -  eps - the eigensolver object

397:    Level: advanced

399: .seealso: NEPSLPGetEPS()
400: @*/
401: PetscErrorCode NEPSLPSetEPS(NEP nep,EPS eps)
402: {

409:   PetscTryMethod(nep,"NEPSLPSetEPS_C",(NEP,EPS),(nep,eps));
410:   return(0);
411: }

413: static PetscErrorCode NEPSLPGetEPS_SLP(NEP nep,EPS *eps)
414: {
416:   NEP_SLP        *ctx = (NEP_SLP*)nep->data;

419:   if (!ctx->eps) {
420:     EPSCreate(PetscObjectComm((PetscObject)nep),&ctx->eps);
421:     PetscObjectIncrementTabLevel((PetscObject)ctx->eps,(PetscObject)nep,1);
422:     EPSSetOptionsPrefix(ctx->eps,((PetscObject)nep)->prefix);
423:     EPSAppendOptionsPrefix(ctx->eps,"nep_slp_");
424:     PetscLogObjectParent((PetscObject)nep,(PetscObject)ctx->eps);
425:     PetscObjectSetOptions((PetscObject)ctx->eps,((PetscObject)nep)->options);
426:   }
427:   *eps = ctx->eps;
428:   return(0);
429: }

431: /*@
432:    NEPSLPGetEPS - Retrieve the linear eigensolver object (EPS) associated
433:    to the nonlinear eigenvalue solver.

435:    Not Collective

437:    Input Parameter:
438: .  nep - nonlinear eigenvalue solver

440:    Output Parameter:
441: .  eps - the eigensolver object

443:    Level: advanced

445: .seealso: NEPSLPSetEPS()
446: @*/
447: PetscErrorCode NEPSLPGetEPS(NEP nep,EPS *eps)
448: {

454:   PetscUseMethod(nep,"NEPSLPGetEPS_C",(NEP,EPS*),(nep,eps));
455:   return(0);
456: }

458: static PetscErrorCode NEPSLPSetEPSLeft_SLP(NEP nep,EPS eps)
459: {
461:   NEP_SLP        *ctx = (NEP_SLP*)nep->data;

464:   PetscObjectReference((PetscObject)eps);
465:   EPSDestroy(&ctx->epsts);
466:   ctx->epsts = eps;
467:   PetscLogObjectParent((PetscObject)nep,(PetscObject)ctx->epsts);
468:   nep->state = NEP_STATE_INITIAL;
469:   return(0);
470: }

472: /*@
473:    NEPSLPSetEPSLeft - Associate a linear eigensolver object (EPS) to the
474:    nonlinear eigenvalue solver, used to compute left eigenvectors in the
475:    two-sided variant of SLP.

477:    Collective on nep

479:    Input Parameters:
480: +  nep - nonlinear eigenvalue solver
481: -  eps - the eigensolver object

483:    Level: advanced

485: .seealso: NEPSLPGetEPSLeft(), NEPSetTwoSided()
486: @*/
487: PetscErrorCode NEPSLPSetEPSLeft(NEP nep,EPS eps)
488: {

495:   PetscTryMethod(nep,"NEPSLPSetEPSLeft_C",(NEP,EPS),(nep,eps));
496:   return(0);
497: }

499: static PetscErrorCode NEPSLPGetEPSLeft_SLP(NEP nep,EPS *eps)
500: {
502:   NEP_SLP        *ctx = (NEP_SLP*)nep->data;

505:   if (!ctx->epsts) {
506:     EPSCreate(PetscObjectComm((PetscObject)nep),&ctx->epsts);
507:     PetscObjectIncrementTabLevel((PetscObject)ctx->epsts,(PetscObject)nep,1);
508:     EPSSetOptionsPrefix(ctx->epsts,((PetscObject)nep)->prefix);
509:     EPSAppendOptionsPrefix(ctx->epsts,"nep_slp_left_");
510:     PetscLogObjectParent((PetscObject)nep,(PetscObject)ctx->epsts);
511:     PetscObjectSetOptions((PetscObject)ctx->epsts,((PetscObject)nep)->options);
512:   }
513:   *eps = ctx->epsts;
514:   return(0);
515: }

517: /*@
518:    NEPSLPGetEPSLeft - Retrieve the linear eigensolver object (EPS) associated
519:    to the nonlinear eigenvalue solver, used to compute left eigenvectors in the
520:    two-sided variant of SLP.

522:    Not Collective

524:    Input Parameter:
525: .  nep - nonlinear eigenvalue solver

527:    Output Parameter:
528: .  eps - the eigensolver object

530:    Level: advanced

532: .seealso: NEPSLPSetEPSLeft(), NEPSetTwoSided()
533: @*/
534: PetscErrorCode NEPSLPGetEPSLeft(NEP nep,EPS *eps)
535: {

541:   PetscUseMethod(nep,"NEPSLPGetEPSLeft_C",(NEP,EPS*),(nep,eps));
542:   return(0);
543: }

545: static PetscErrorCode NEPSLPSetKSP_SLP(NEP nep,KSP ksp)
546: {
548:   NEP_SLP        *ctx = (NEP_SLP*)nep->data;

551:   PetscObjectReference((PetscObject)ksp);
552:   KSPDestroy(&ctx->ksp);
553:   ctx->ksp = ksp;
554:   PetscLogObjectParent((PetscObject)nep,(PetscObject)ctx->ksp);
555:   nep->state = NEP_STATE_INITIAL;
556:   return(0);
557: }

559: /*@
560:    NEPSLPSetKSP - Associate a linear solver object (KSP) to the nonlinear
561:    eigenvalue solver.

563:    Collective on nep

565:    Input Parameters:
566: +  nep - eigenvalue solver
567: -  ksp - the linear solver object

569:    Level: advanced

571: .seealso: NEPSLPGetKSP()
572: @*/
573: PetscErrorCode NEPSLPSetKSP(NEP nep,KSP ksp)
574: {

581:   PetscTryMethod(nep,"NEPSLPSetKSP_C",(NEP,KSP),(nep,ksp));
582:   return(0);
583: }

585: static PetscErrorCode NEPSLPGetKSP_SLP(NEP nep,KSP *ksp)
586: {
588:   NEP_SLP        *ctx = (NEP_SLP*)nep->data;

591:   if (!ctx->ksp) {
592:     KSPCreate(PetscObjectComm((PetscObject)nep),&ctx->ksp);
593:     PetscObjectIncrementTabLevel((PetscObject)ctx->ksp,(PetscObject)nep,1);
594:     KSPSetOptionsPrefix(ctx->ksp,((PetscObject)nep)->prefix);
595:     KSPAppendOptionsPrefix(ctx->ksp,"nep_slp_");
596:     PetscLogObjectParent((PetscObject)nep,(PetscObject)ctx->ksp);
597:     KSPSetErrorIfNotConverged(ctx->ksp,PETSC_TRUE);
598:     KSPSetTolerances(ctx->ksp,SLEPC_DEFAULT_TOL,PETSC_DEFAULT,PETSC_DEFAULT,PETSC_DEFAULT);
599:   }
600:   *ksp = ctx->ksp;
601:   return(0);
602: }

604: /*@
605:    NEPSLPGetKSP - Retrieve the linear solver object (KSP) associated with
606:    the nonlinear eigenvalue solver.

608:    Not Collective

610:    Input Parameter:
611: .  nep - nonlinear eigenvalue solver

613:    Output Parameter:
614: .  ksp - the linear solver object

616:    Level: advanced

618: .seealso: NEPSLPSetKSP()
619: @*/
620: PetscErrorCode NEPSLPGetKSP(NEP nep,KSP *ksp)
621: {

627:   PetscUseMethod(nep,"NEPSLPGetKSP_C",(NEP,KSP*),(nep,ksp));
628:   return(0);
629: }

631: PetscErrorCode NEPView_SLP(NEP nep,PetscViewer viewer)
632: {
634:   NEP_SLP        *ctx = (NEP_SLP*)nep->data;
635:   PetscBool      isascii;

638:   PetscObjectTypeCompare((PetscObject)viewer,PETSCVIEWERASCII,&isascii);
639:   if (isascii) {
640:     if (ctx->deftol) {
641:       PetscViewerASCIIPrintf(viewer,"  deflation threshold: %g\n",(double)ctx->deftol);
642:     }
643:     if (!ctx->eps) { NEPSLPGetEPS(nep,&ctx->eps); }
644:     PetscViewerASCIIPushTab(viewer);
645:     EPSView(ctx->eps,viewer);
646:     if (nep->twosided) {
647:       if (!ctx->epsts) { NEPSLPGetEPSLeft(nep,&ctx->epsts); }
648:       EPSView(ctx->epsts,viewer);
649:     }
650:     if (!ctx->ksp) { NEPSLPGetKSP(nep,&ctx->ksp); }
651:     KSPView(ctx->ksp,viewer);
652:     PetscViewerASCIIPopTab(viewer);
653:   }
654:   return(0);
655: }

657: PetscErrorCode NEPReset_SLP(NEP nep)
658: {
660:   NEP_SLP        *ctx = (NEP_SLP*)nep->data;

663:   EPSReset(ctx->eps);
664:   if (nep->twosided) { EPSReset(ctx->epsts); }
665:   KSPReset(ctx->ksp);
666:   return(0);
667: }

669: PetscErrorCode NEPDestroy_SLP(NEP nep)
670: {
672:   NEP_SLP        *ctx = (NEP_SLP*)nep->data;

675:   KSPDestroy(&ctx->ksp);
676:   EPSDestroy(&ctx->eps);
677:   EPSDestroy(&ctx->epsts);
678:   PetscFree(nep->data);
679:   PetscObjectComposeFunction((PetscObject)nep,"NEPSLPSetDeflationThreshold_C",NULL);
680:   PetscObjectComposeFunction((PetscObject)nep,"NEPSLPGetDeflationThreshold_C",NULL);
681:   PetscObjectComposeFunction((PetscObject)nep,"NEPSLPSetEPS_C",NULL);
682:   PetscObjectComposeFunction((PetscObject)nep,"NEPSLPGetEPS_C",NULL);
683:   PetscObjectComposeFunction((PetscObject)nep,"NEPSLPSetEPSLeft_C",NULL);
684:   PetscObjectComposeFunction((PetscObject)nep,"NEPSLPGetEPSLeft_C",NULL);
685:   PetscObjectComposeFunction((PetscObject)nep,"NEPSLPSetKSP_C",NULL);
686:   PetscObjectComposeFunction((PetscObject)nep,"NEPSLPGetKSP_C",NULL);
687:   return(0);
688: }

690: SLEPC_EXTERN PetscErrorCode NEPCreate_SLP(NEP nep)
691: {
693:   NEP_SLP        *ctx;

696:   PetscNewLog(nep,&ctx);
697:   nep->data = (void*)ctx;

699:   nep->useds = PETSC_TRUE;
700:   nep->hasts = PETSC_TRUE;

702:   ctx->deftol = 0.0;

704:   nep->ops->solve          = NEPSolve_SLP;
705:   nep->ops->setup          = NEPSetUp_SLP;
706:   nep->ops->setfromoptions = NEPSetFromOptions_SLP;
707:   nep->ops->reset          = NEPReset_SLP;
708:   nep->ops->destroy        = NEPDestroy_SLP;
709:   nep->ops->view           = NEPView_SLP;
710:   nep->ops->computevectors = NEPComputeVectors_Schur;

712:   PetscObjectComposeFunction((PetscObject)nep,"NEPSLPSetDeflationThreshold_C",NEPSLPSetDeflationThreshold_SLP);
713:   PetscObjectComposeFunction((PetscObject)nep,"NEPSLPGetDeflationThreshold_C",NEPSLPGetDeflationThreshold_SLP);
714:   PetscObjectComposeFunction((PetscObject)nep,"NEPSLPSetEPS_C",NEPSLPSetEPS_SLP);
715:   PetscObjectComposeFunction((PetscObject)nep,"NEPSLPGetEPS_C",NEPSLPGetEPS_SLP);
716:   PetscObjectComposeFunction((PetscObject)nep,"NEPSLPSetEPSLeft_C",NEPSLPSetEPSLeft_SLP);
717:   PetscObjectComposeFunction((PetscObject)nep,"NEPSLPGetEPSLeft_C",NEPSLPGetEPSLeft_SLP);
718:   PetscObjectComposeFunction((PetscObject)nep,"NEPSLPSetKSP_C",NEPSLPSetKSP_SLP);
719:   PetscObjectComposeFunction((PetscObject)nep,"NEPSLPGetKSP_C",NEPSLPGetKSP_SLP);
720:   return(0);
721: }