Actual source code: slp.c
slepc-3.13.2 2020-05-12
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: }