LCOV - code coverage report
Current view: top level - nep/impls/slp - slp.c (source / functions) Hit Total Coverage
Test: SLEPc Lines: 330 354 93.2 %
Date: 2024-12-18 00:51:33 Functions: 24 26 92.3 %
Legend: Lines: hit not hit

          Line data    Source code
       1             : /*
       2             :    - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
       3             :    SLEPc - Scalable Library for Eigenvalue Problem Computations
       4             :    Copyright (c) 2002-, Universitat Politecnica de Valencia, Spain
       5             : 
       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"
      12             : 
      13             :    Method: Successive linear problems
      14             : 
      15             :    Algorithm:
      16             : 
      17             :        Newton-type iteration based on first order Taylor approximation.
      18             : 
      19             :    References:
      20             : 
      21             :        [1] A. Ruhe, "Algorithms for the nonlinear eigenvalue problem", SIAM J.
      22             :            Numer. Anal. 10(4):674-689, 1973.
      23             : */
      24             : 
      25             : #include <slepc/private/nepimpl.h>         /*I "slepcnep.h" I*/
      26             : #include <../src/nep/impls/nepdefl.h>
      27             : #include "slp.h"
      28             : 
      29             : typedef struct {
      30             :   NEP_EXT_OP extop;
      31             :   Vec        w;
      32             : } NEP_SLP_MATSHELL;
      33             : 
      34          29 : static PetscErrorCode NEPSetUp_SLP(NEP nep)
      35             : {
      36          29 :   NEP_SLP        *ctx = (NEP_SLP*)nep->data;
      37          29 :   PetscBool      flg;
      38          29 :   ST             st;
      39             : 
      40          29 :   PetscFunctionBegin;
      41          29 :   if (nep->ncv!=PETSC_DETERMINE) PetscCall(PetscInfo(nep,"Setting ncv = nev, ignoring user-provided value\n"));
      42          29 :   nep->ncv = nep->nev;
      43          29 :   if (nep->mpd!=PETSC_DETERMINE) PetscCall(PetscInfo(nep,"Setting mpd = nev, ignoring user-provided value\n"));
      44          29 :   nep->mpd = nep->nev;
      45          29 :   PetscCheck(nep->ncv<=nep->nev+nep->mpd,PetscObjectComm((PetscObject)nep),PETSC_ERR_USER_INPUT,"The value of ncv must not be larger than nev+mpd");
      46          29 :   if (nep->max_it==PETSC_DETERMINE) nep->max_it = PetscMax(5000,2*nep->n/nep->ncv);
      47          29 :   if (!nep->which) nep->which = NEP_TARGET_MAGNITUDE;
      48          29 :   PetscCheck(nep->which==NEP_TARGET_MAGNITUDE,PetscObjectComm((PetscObject)nep),PETSC_ERR_SUP,"This solver supports only target magnitude eigenvalues");
      49          29 :   NEPCheckUnsupported(nep,NEP_FEATURE_REGION);
      50             : 
      51          29 :   if (!ctx->eps) PetscCall(NEPSLPGetEPS(nep,&ctx->eps));
      52          29 :   PetscCall(EPSGetST(ctx->eps,&st));
      53          29 :   PetscCall(PetscObjectTypeCompareAny((PetscObject)st,&flg,STSINVERT,STCAYLEY,""));
      54          29 :   PetscCheck(!flg,PetscObjectComm((PetscObject)nep),PETSC_ERR_SUP,"SLP does not support spectral transformation");
      55          29 :   PetscCall(EPSSetDimensions(ctx->eps,1,PETSC_DECIDE,PETSC_DECIDE));
      56          29 :   PetscCall(EPSSetWhichEigenpairs(ctx->eps,EPS_LARGEST_MAGNITUDE));
      57          43 :   PetscCall(EPSSetTolerances(ctx->eps,SlepcDefaultTol(nep->tol)/10.0,nep->max_it));
      58          29 :   if (nep->tol==(PetscReal)PETSC_DETERMINE) nep->tol = SLEPC_DEFAULT_TOL;
      59          29 :   if (ctx->deftol==(PetscReal)PETSC_DETERMINE) ctx->deftol = nep->tol;
      60             : 
      61          29 :   if (nep->twosided) {
      62           5 :     nep->ops->solve = NEPSolve_SLP_Twosided;
      63           5 :     nep->ops->computevectors = NULL;
      64           5 :     if (!ctx->epsts) PetscCall(NEPSLPGetEPSLeft(nep,&ctx->epsts));
      65           5 :     PetscCall(EPSGetST(ctx->epsts,&st));
      66           5 :     PetscCall(PetscObjectTypeCompareAny((PetscObject)st,&flg,STSINVERT,STCAYLEY,""));
      67           5 :     PetscCheck(!flg,PetscObjectComm((PetscObject)nep),PETSC_ERR_SUP,"SLP does not support spectral transformation");
      68           5 :     PetscCall(EPSSetDimensions(ctx->epsts,1,PETSC_DECIDE,PETSC_DECIDE));
      69           5 :     PetscCall(EPSSetWhichEigenpairs(ctx->epsts,EPS_LARGEST_MAGNITUDE));
      70           5 :     PetscCall(EPSSetTolerances(ctx->epsts,SlepcDefaultTol(nep->tol)/10.0,nep->max_it));
      71             :   } else {
      72          24 :     nep->ops->solve = NEPSolve_SLP;
      73          24 :     nep->ops->computevectors = NEPComputeVectors_Schur;
      74             :   }
      75          29 :   PetscCall(NEPAllocateSolution(nep,0));
      76          29 :   PetscFunctionReturn(PETSC_SUCCESS);
      77             : }
      78             : 
      79        1373 : static PetscErrorCode MatMult_SLP(Mat M,Vec x,Vec y)
      80             : {
      81        1373 :   NEP_SLP_MATSHELL *ctx;
      82             : 
      83        1373 :   PetscFunctionBegin;
      84        1373 :   PetscCall(MatShellGetContext(M,&ctx));
      85        1373 :   PetscCall(MatMult(ctx->extop->MJ,x,ctx->w));
      86        1373 :   PetscCall(NEPDeflationFunctionSolve(ctx->extop,ctx->w,y));
      87        1373 :   PetscFunctionReturn(PETSC_SUCCESS);
      88             : }
      89             : 
      90          24 : static PetscErrorCode MatDestroy_SLP(Mat M)
      91             : {
      92          24 :   NEP_SLP_MATSHELL *ctx;
      93             : 
      94          24 :   PetscFunctionBegin;
      95          24 :   PetscCall(MatShellGetContext(M,&ctx));
      96          24 :   PetscCall(VecDestroy(&ctx->w));
      97          24 :   PetscCall(PetscFree(ctx));
      98          24 :   PetscFunctionReturn(PETSC_SUCCESS);
      99             : }
     100             : 
     101             : #if defined(PETSC_HAVE_CUDA) || defined(PETSC_HAVE_HIP)
     102             : static PetscErrorCode MatCreateVecs_SLP(Mat M,Vec *left,Vec *right)
     103             : {
     104             :   NEP_SLP_MATSHELL *ctx;
     105             : 
     106             :   PetscFunctionBegin;
     107             :   PetscCall(MatShellGetContext(M,&ctx));
     108             :   if (right) PetscCall(VecDuplicate(ctx->w,right));
     109             :   if (left) PetscCall(VecDuplicate(ctx->w,left));
     110             :   PetscFunctionReturn(PETSC_SUCCESS);
     111             : }
     112             : #endif
     113             : 
     114          80 : static PetscErrorCode NEPSLPSetUpLinearEP(NEP nep,NEP_EXT_OP extop,PetscScalar lambda,Vec u,PetscBool ini)
     115             : {
     116          80 :   NEP_SLP          *slpctx = (NEP_SLP*)nep->data;
     117          80 :   Mat              Mshell;
     118          80 :   PetscInt         nloc,mloc;
     119          80 :   NEP_SLP_MATSHELL *shellctx;
     120             : 
     121          80 :   PetscFunctionBegin;
     122          80 :   if (ini) {
     123             :     /* Create mat shell */
     124          24 :     PetscCall(PetscNew(&shellctx));
     125          24 :     shellctx->extop = extop;
     126          24 :     PetscCall(NEPDeflationCreateVec(extop,&shellctx->w));
     127          24 :     PetscCall(MatGetLocalSize(nep->function,&mloc,&nloc));
     128          24 :     nloc += extop->szd; mloc += extop->szd;
     129          24 :     PetscCall(MatCreateShell(PetscObjectComm((PetscObject)nep),nloc,mloc,PETSC_DETERMINE,PETSC_DETERMINE,shellctx,&Mshell));
     130          24 :     PetscCall(MatShellSetOperation(Mshell,MATOP_MULT,(void(*)(void))MatMult_SLP));
     131          24 :     PetscCall(MatShellSetOperation(Mshell,MATOP_DESTROY,(void(*)(void))MatDestroy_SLP));
     132             : #if defined(PETSC_HAVE_CUDA) || defined(PETSC_HAVE_HIP)
     133             :     PetscCall(MatShellSetOperation(Mshell,MATOP_CREATE_VECS,(void(*)(void))MatCreateVecs_SLP));
     134             : #endif
     135          24 :     PetscCall(EPSSetOperators(slpctx->eps,Mshell,NULL));
     136          24 :     PetscCall(MatDestroy(&Mshell));
     137             :   }
     138          80 :   PetscCall(NEPDeflationSolveSetUp(extop,lambda));
     139          80 :   PetscCall(NEPDeflationComputeJacobian(extop,lambda,NULL));
     140          80 :   PetscCall(EPSSetInitialSpace(slpctx->eps,1,&u));
     141          80 :   PetscFunctionReturn(PETSC_SUCCESS);
     142             : }
     143             : 
     144          24 : PetscErrorCode NEPSolve_SLP(NEP nep)
     145             : {
     146          24 :   NEP_SLP           *ctx = (NEP_SLP*)nep->data;
     147          24 :   Mat               F,H,A;
     148          24 :   Vec               uu,u,r;
     149          24 :   PetscScalar       sigma,lambda,mu,im;
     150          24 :   PetscReal         resnorm;
     151          24 :   PetscInt          nconv;
     152          24 :   PetscBool         skip=PETSC_FALSE,lock=PETSC_FALSE;
     153          24 :   NEP_EXT_OP        extop=NULL;    /* Extended operator for deflation */
     154             : 
     155          24 :   PetscFunctionBegin;
     156             :   /* get initial approximation of eigenvalue and eigenvector */
     157          24 :   PetscCall(NEPGetDefaultShift(nep,&sigma));
     158          24 :   if (!nep->nini) PetscCall(BVSetRandomColumn(nep->V,0));
     159          24 :   lambda = sigma;
     160          24 :   if (!ctx->ksp) PetscCall(NEPSLPGetKSP(nep,&ctx->ksp));
     161          24 :   PetscCall(NEPDeflationInitialize(nep,nep->V,ctx->ksp,PETSC_TRUE,nep->nev,&extop));
     162          24 :   PetscCall(NEPDeflationCreateVec(extop,&u));
     163          24 :   PetscCall(VecDuplicate(u,&r));
     164          24 :   PetscCall(BVGetColumn(nep->V,0,&uu));
     165          24 :   PetscCall(NEPDeflationCopyToExtendedVec(extop,uu,NULL,u,PETSC_FALSE));
     166          24 :   PetscCall(BVRestoreColumn(nep->V,0,&uu));
     167             : 
     168             :   /* Restart loop */
     169         144 :   while (nep->reason == NEP_CONVERGED_ITERATING) {
     170         120 :     nep->its++;
     171             : 
     172             :     /* form residual,  r = T(lambda)*u (used in convergence test only) */
     173         120 :     PetscCall(NEPDeflationComputeFunction(extop,lambda,&F));
     174         120 :     PetscCall(MatMult(F,u,r));
     175             : 
     176             :     /* convergence test */
     177         120 :     PetscCall(VecNorm(r,NORM_2,&resnorm));
     178         120 :     PetscCall((*nep->converged)(nep,lambda,0,resnorm,&nep->errest[nep->nconv],nep->convergedctx));
     179         120 :     nep->eigr[nep->nconv] = lambda;
     180         120 :     if (nep->errest[nep->nconv]<=nep->tol || nep->errest[nep->nconv]<=ctx->deftol) {
     181          40 :       if (nep->errest[nep->nconv]<=ctx->deftol && !extop->ref && nep->nconv) {
     182          16 :         PetscCall(NEPDeflationExtractEigenpair(extop,nep->nconv,u,lambda,nep->ds));
     183          16 :         PetscCall(NEPDeflationSetRefine(extop,PETSC_TRUE));
     184          16 :         PetscCall(MatMult(F,u,r));
     185          16 :         PetscCall(VecNorm(r,NORM_2,&resnorm));
     186          16 :         PetscCall((*nep->converged)(nep,lambda,0,resnorm,&nep->errest[nep->nconv],nep->convergedctx));
     187          16 :         if (nep->errest[nep->nconv]<=nep->tol) lock = PETSC_TRUE;
     188          24 :       } else if (nep->errest[nep->nconv]<=nep->tol) lock = PETSC_TRUE;
     189             :     }
     190             : 
     191          80 :     if (lock) {
     192          40 :       PetscCall(NEPDeflationSetRefine(extop,PETSC_FALSE));
     193          40 :       nep->nconv = nep->nconv + 1;
     194          40 :       skip = PETSC_TRUE;
     195          40 :       lock = PETSC_FALSE;
     196          40 :       PetscCall(NEPDeflationLocking(extop,u,lambda));
     197             :     }
     198         120 :     PetscCall((*nep->stopping)(nep,nep->its,nep->max_it,nep->nconv,nep->nev,&nep->reason,nep->stoppingctx));
     199         120 :     if (!skip || nep->reason>0) PetscCall(NEPMonitor(nep,nep->its,nep->nconv,nep->eigr,nep->eigi,nep->errest,(nep->reason>0)?nep->nconv:nep->nconv+1));
     200             : 
     201         120 :     if (nep->reason == NEP_CONVERGED_ITERATING) {
     202          96 :       if (!skip) {
     203             :         /* evaluate T(lambda) and T'(lambda) */
     204          80 :         PetscCall(NEPSLPSetUpLinearEP(nep,extop,lambda,u,nep->its==1?PETSC_TRUE:PETSC_FALSE));
     205             :         /* compute new eigenvalue correction mu and eigenvector approximation u */
     206          80 :         PetscCall(EPSSolve(ctx->eps));
     207          80 :         PetscCall(EPSGetConverged(ctx->eps,&nconv));
     208          80 :         if (!nconv) {
     209           0 :           PetscCall(PetscInfo(nep,"iter=%" PetscInt_FMT ", inner iteration failed, stopping solve\n",nep->its));
     210           0 :           nep->reason = NEP_DIVERGED_LINEAR_SOLVE;
     211           0 :           break;
     212             :         }
     213          80 :         PetscCall(EPSGetEigenpair(ctx->eps,0,&mu,&im,u,NULL));
     214          80 :         mu = 1.0/mu;
     215          80 :         PetscCheck(PetscAbsScalar(im)<PETSC_MACHINE_EPSILON,PetscObjectComm((PetscObject)nep),PETSC_ERR_SUP,"Complex eigenvalue approximation - not implemented in real scalars");
     216             :       } else {
     217          16 :         nep->its--;  /* do not count this as a full iteration */
     218             :         /* use second eigenpair computed in previous iteration */
     219          16 :         PetscCall(EPSGetConverged(ctx->eps,&nconv));
     220          16 :         if (nconv>=2) {
     221          16 :           PetscCall(EPSGetEigenpair(ctx->eps,1,&mu,&im,u,NULL));
     222          16 :           mu = 1.0/mu;
     223             :         } else {
     224           0 :           PetscCall(NEPDeflationSetRandomVec(extop,u));
     225           0 :           mu = lambda-sigma;
     226             :         }
     227             :         skip = PETSC_FALSE;
     228             :       }
     229             :       /* correct eigenvalue */
     230          96 :       lambda = lambda - mu;
     231             :     }
     232             :   }
     233          24 :   PetscCall(NEPDeflationGetInvariantPair(extop,NULL,&H));
     234          24 :   PetscCall(DSSetType(nep->ds,DSNHEP));
     235          24 :   PetscCall(DSAllocate(nep->ds,PetscMax(nep->nconv,1)));
     236          24 :   PetscCall(DSSetDimensions(nep->ds,nep->nconv,0,nep->nconv));
     237          24 :   PetscCall(DSGetMat(nep->ds,DS_MAT_A,&A));
     238          24 :   PetscCall(MatCopy(H,A,SAME_NONZERO_PATTERN));
     239          24 :   PetscCall(DSRestoreMat(nep->ds,DS_MAT_A,&A));
     240          24 :   PetscCall(MatDestroy(&H));
     241          24 :   PetscCall(DSSolve(nep->ds,nep->eigr,nep->eigi));
     242          24 :   PetscCall(NEPDeflationReset(extop));
     243          24 :   PetscCall(VecDestroy(&u));
     244          24 :   PetscCall(VecDestroy(&r));
     245          24 :   PetscFunctionReturn(PETSC_SUCCESS);
     246             : }
     247             : 
     248          25 : static PetscErrorCode NEPSetFromOptions_SLP(NEP nep,PetscOptionItems *PetscOptionsObject)
     249             : {
     250          25 :   NEP_SLP        *ctx = (NEP_SLP*)nep->data;
     251          25 :   PetscBool      flg;
     252          25 :   PetscReal      r;
     253             : 
     254          25 :   PetscFunctionBegin;
     255          25 :   PetscOptionsHeadBegin(PetscOptionsObject,"NEP SLP Options");
     256             : 
     257          25 :     r = 0.0;
     258          25 :     PetscCall(PetscOptionsReal("-nep_slp_deflation_threshold","Tolerance used as a threshold for including deflated eigenpairs","NEPSLPSetDeflationThreshold",ctx->deftol,&r,&flg));
     259          25 :     if (flg) PetscCall(NEPSLPSetDeflationThreshold(nep,r));
     260             : 
     261          25 :   PetscOptionsHeadEnd();
     262             : 
     263          25 :   if (!ctx->eps) PetscCall(NEPSLPGetEPS(nep,&ctx->eps));
     264          25 :   PetscCall(EPSSetFromOptions(ctx->eps));
     265          25 :   if (nep->twosided) {
     266           5 :     if (!ctx->epsts) PetscCall(NEPSLPGetEPSLeft(nep,&ctx->epsts));
     267           5 :     PetscCall(EPSSetFromOptions(ctx->epsts));
     268             :   }
     269          25 :   if (!ctx->ksp) PetscCall(NEPSLPGetKSP(nep,&ctx->ksp));
     270          25 :   PetscCall(KSPSetFromOptions(ctx->ksp));
     271          25 :   PetscFunctionReturn(PETSC_SUCCESS);
     272             : }
     273             : 
     274           3 : static PetscErrorCode NEPSLPSetDeflationThreshold_SLP(NEP nep,PetscReal deftol)
     275             : {
     276           3 :   NEP_SLP *ctx = (NEP_SLP*)nep->data;
     277             : 
     278           3 :   PetscFunctionBegin;
     279           3 :   if (deftol == (PetscReal)PETSC_DEFAULT || deftol == (PetscReal)PETSC_DECIDE) {
     280           0 :     ctx->deftol = PETSC_DETERMINE;
     281           0 :     nep->state  = NEP_STATE_INITIAL;
     282             :   } else {
     283           3 :     PetscCheck(deftol>0.0,PetscObjectComm((PetscObject)nep),PETSC_ERR_ARG_OUTOFRANGE,"Illegal value of deftol. Must be > 0");
     284           3 :     ctx->deftol = deftol;
     285             :   }
     286           3 :   PetscFunctionReturn(PETSC_SUCCESS);
     287             : }
     288             : 
     289             : /*@
     290             :    NEPSLPSetDeflationThreshold - Sets the threshold value used to switch between
     291             :    deflated and non-deflated iteration.
     292             : 
     293             :    Logically Collective
     294             : 
     295             :    Input Parameters:
     296             : +  nep    - nonlinear eigenvalue solver
     297             : -  deftol - the threshold value
     298             : 
     299             :    Options Database Keys:
     300             : .  -nep_slp_deflation_threshold <deftol> - set the threshold
     301             : 
     302             :    Notes:
     303             :    Normally, the solver iterates on the extended problem in order to deflate
     304             :    previously converged eigenpairs. If this threshold is set to a nonzero value,
     305             :    then once the residual error is below this threshold the solver will
     306             :    continue the iteration without deflation. The intention is to be able to
     307             :    improve the current eigenpair further, despite having previous eigenpairs
     308             :    with somewhat bad precision.
     309             : 
     310             :    Level: advanced
     311             : 
     312             : .seealso: NEPSLPGetDeflationThreshold()
     313             : @*/
     314           3 : PetscErrorCode NEPSLPSetDeflationThreshold(NEP nep,PetscReal deftol)
     315             : {
     316           3 :   PetscFunctionBegin;
     317           3 :   PetscValidHeaderSpecific(nep,NEP_CLASSID,1);
     318           9 :   PetscValidLogicalCollectiveReal(nep,deftol,2);
     319           3 :   PetscTryMethod(nep,"NEPSLPSetDeflationThreshold_C",(NEP,PetscReal),(nep,deftol));
     320           3 :   PetscFunctionReturn(PETSC_SUCCESS);
     321             : }
     322             : 
     323           1 : static PetscErrorCode NEPSLPGetDeflationThreshold_SLP(NEP nep,PetscReal *deftol)
     324             : {
     325           1 :   NEP_SLP *ctx = (NEP_SLP*)nep->data;
     326             : 
     327           1 :   PetscFunctionBegin;
     328           1 :   *deftol = ctx->deftol;
     329           1 :   PetscFunctionReturn(PETSC_SUCCESS);
     330             : }
     331             : 
     332             : /*@
     333             :    NEPSLPGetDeflationThreshold - Returns the threshold value that controls deflation.
     334             : 
     335             :    Not Collective
     336             : 
     337             :    Input Parameter:
     338             : .  nep - nonlinear eigenvalue solver
     339             : 
     340             :    Output Parameter:
     341             : .  deftol - the threshold
     342             : 
     343             :    Level: advanced
     344             : 
     345             : .seealso: NEPSLPSetDeflationThreshold()
     346             : @*/
     347           1 : PetscErrorCode NEPSLPGetDeflationThreshold(NEP nep,PetscReal *deftol)
     348             : {
     349           1 :   PetscFunctionBegin;
     350           1 :   PetscValidHeaderSpecific(nep,NEP_CLASSID,1);
     351           1 :   PetscAssertPointer(deftol,2);
     352           1 :   PetscUseMethod(nep,"NEPSLPGetDeflationThreshold_C",(NEP,PetscReal*),(nep,deftol));
     353           1 :   PetscFunctionReturn(PETSC_SUCCESS);
     354             : }
     355             : 
     356           2 : static PetscErrorCode NEPSLPSetEPS_SLP(NEP nep,EPS eps)
     357             : {
     358           2 :   NEP_SLP        *ctx = (NEP_SLP*)nep->data;
     359             : 
     360           2 :   PetscFunctionBegin;
     361           2 :   PetscCall(PetscObjectReference((PetscObject)eps));
     362           2 :   PetscCall(EPSDestroy(&ctx->eps));
     363           2 :   ctx->eps = eps;
     364           2 :   nep->state = NEP_STATE_INITIAL;
     365           2 :   PetscFunctionReturn(PETSC_SUCCESS);
     366             : }
     367             : 
     368             : /*@
     369             :    NEPSLPSetEPS - Associate a linear eigensolver object (EPS) to the
     370             :    nonlinear eigenvalue solver.
     371             : 
     372             :    Collective
     373             : 
     374             :    Input Parameters:
     375             : +  nep - nonlinear eigenvalue solver
     376             : -  eps - the eigensolver object
     377             : 
     378             :    Level: advanced
     379             : 
     380             : .seealso: NEPSLPGetEPS()
     381             : @*/
     382           2 : PetscErrorCode NEPSLPSetEPS(NEP nep,EPS eps)
     383             : {
     384           2 :   PetscFunctionBegin;
     385           2 :   PetscValidHeaderSpecific(nep,NEP_CLASSID,1);
     386           2 :   PetscValidHeaderSpecific(eps,EPS_CLASSID,2);
     387           2 :   PetscCheckSameComm(nep,1,eps,2);
     388           2 :   PetscTryMethod(nep,"NEPSLPSetEPS_C",(NEP,EPS),(nep,eps));
     389           2 :   PetscFunctionReturn(PETSC_SUCCESS);
     390             : }
     391             : 
     392          23 : static PetscErrorCode NEPSLPGetEPS_SLP(NEP nep,EPS *eps)
     393             : {
     394          23 :   NEP_SLP        *ctx = (NEP_SLP*)nep->data;
     395             : 
     396          23 :   PetscFunctionBegin;
     397          23 :   if (!ctx->eps) {
     398          23 :     PetscCall(EPSCreate(PetscObjectComm((PetscObject)nep),&ctx->eps));
     399          23 :     PetscCall(PetscObjectIncrementTabLevel((PetscObject)ctx->eps,(PetscObject)nep,1));
     400          23 :     PetscCall(EPSSetOptionsPrefix(ctx->eps,((PetscObject)nep)->prefix));
     401          23 :     PetscCall(EPSAppendOptionsPrefix(ctx->eps,"nep_slp_"));
     402          23 :     PetscCall(PetscObjectSetOptions((PetscObject)ctx->eps,((PetscObject)nep)->options));
     403             :   }
     404          23 :   *eps = ctx->eps;
     405          23 :   PetscFunctionReturn(PETSC_SUCCESS);
     406             : }
     407             : 
     408             : /*@
     409             :    NEPSLPGetEPS - Retrieve the linear eigensolver object (EPS) associated
     410             :    to the nonlinear eigenvalue solver.
     411             : 
     412             :    Collective
     413             : 
     414             :    Input Parameter:
     415             : .  nep - nonlinear eigenvalue solver
     416             : 
     417             :    Output Parameter:
     418             : .  eps - the eigensolver object
     419             : 
     420             :    Level: advanced
     421             : 
     422             : .seealso: NEPSLPSetEPS()
     423             : @*/
     424          23 : PetscErrorCode NEPSLPGetEPS(NEP nep,EPS *eps)
     425             : {
     426          23 :   PetscFunctionBegin;
     427          23 :   PetscValidHeaderSpecific(nep,NEP_CLASSID,1);
     428          23 :   PetscAssertPointer(eps,2);
     429          23 :   PetscUseMethod(nep,"NEPSLPGetEPS_C",(NEP,EPS*),(nep,eps));
     430          23 :   PetscFunctionReturn(PETSC_SUCCESS);
     431             : }
     432             : 
     433           0 : static PetscErrorCode NEPSLPSetEPSLeft_SLP(NEP nep,EPS eps)
     434             : {
     435           0 :   NEP_SLP        *ctx = (NEP_SLP*)nep->data;
     436             : 
     437           0 :   PetscFunctionBegin;
     438           0 :   PetscCall(PetscObjectReference((PetscObject)eps));
     439           0 :   PetscCall(EPSDestroy(&ctx->epsts));
     440           0 :   ctx->epsts = eps;
     441           0 :   nep->state = NEP_STATE_INITIAL;
     442           0 :   PetscFunctionReturn(PETSC_SUCCESS);
     443             : }
     444             : 
     445             : /*@
     446             :    NEPSLPSetEPSLeft - Associate a linear eigensolver object (EPS) to the
     447             :    nonlinear eigenvalue solver, used to compute left eigenvectors in the
     448             :    two-sided variant of SLP.
     449             : 
     450             :    Collective
     451             : 
     452             :    Input Parameters:
     453             : +  nep - nonlinear eigenvalue solver
     454             : -  eps - the eigensolver object
     455             : 
     456             :    Level: advanced
     457             : 
     458             : .seealso: NEPSLPGetEPSLeft(), NEPSetTwoSided()
     459             : @*/
     460           0 : PetscErrorCode NEPSLPSetEPSLeft(NEP nep,EPS eps)
     461             : {
     462           0 :   PetscFunctionBegin;
     463           0 :   PetscValidHeaderSpecific(nep,NEP_CLASSID,1);
     464           0 :   PetscValidHeaderSpecific(eps,EPS_CLASSID,2);
     465           0 :   PetscCheckSameComm(nep,1,eps,2);
     466           0 :   PetscTryMethod(nep,"NEPSLPSetEPSLeft_C",(NEP,EPS),(nep,eps));
     467           0 :   PetscFunctionReturn(PETSC_SUCCESS);
     468             : }
     469             : 
     470           5 : static PetscErrorCode NEPSLPGetEPSLeft_SLP(NEP nep,EPS *eps)
     471             : {
     472           5 :   NEP_SLP        *ctx = (NEP_SLP*)nep->data;
     473             : 
     474           5 :   PetscFunctionBegin;
     475           5 :   if (!ctx->epsts) {
     476           5 :     PetscCall(EPSCreate(PetscObjectComm((PetscObject)nep),&ctx->epsts));
     477           5 :     PetscCall(PetscObjectIncrementTabLevel((PetscObject)ctx->epsts,(PetscObject)nep,1));
     478           5 :     PetscCall(EPSSetOptionsPrefix(ctx->epsts,((PetscObject)nep)->prefix));
     479           5 :     PetscCall(EPSAppendOptionsPrefix(ctx->epsts,"nep_slp_left_"));
     480           5 :     PetscCall(PetscObjectSetOptions((PetscObject)ctx->epsts,((PetscObject)nep)->options));
     481             :   }
     482           5 :   *eps = ctx->epsts;
     483           5 :   PetscFunctionReturn(PETSC_SUCCESS);
     484             : }
     485             : 
     486             : /*@
     487             :    NEPSLPGetEPSLeft - Retrieve the linear eigensolver object (EPS) associated
     488             :    to the nonlinear eigenvalue solver, used to compute left eigenvectors in the
     489             :    two-sided variant of SLP.
     490             : 
     491             :    Collective
     492             : 
     493             :    Input Parameter:
     494             : .  nep - nonlinear eigenvalue solver
     495             : 
     496             :    Output Parameter:
     497             : .  eps - the eigensolver object
     498             : 
     499             :    Level: advanced
     500             : 
     501             : .seealso: NEPSLPSetEPSLeft(), NEPSetTwoSided()
     502             : @*/
     503           5 : PetscErrorCode NEPSLPGetEPSLeft(NEP nep,EPS *eps)
     504             : {
     505           5 :   PetscFunctionBegin;
     506           5 :   PetscValidHeaderSpecific(nep,NEP_CLASSID,1);
     507           5 :   PetscAssertPointer(eps,2);
     508           5 :   PetscUseMethod(nep,"NEPSLPGetEPSLeft_C",(NEP,EPS*),(nep,eps));
     509           5 :   PetscFunctionReturn(PETSC_SUCCESS);
     510             : }
     511             : 
     512           2 : static PetscErrorCode NEPSLPSetKSP_SLP(NEP nep,KSP ksp)
     513             : {
     514           2 :   NEP_SLP        *ctx = (NEP_SLP*)nep->data;
     515             : 
     516           2 :   PetscFunctionBegin;
     517           2 :   PetscCall(PetscObjectReference((PetscObject)ksp));
     518           2 :   PetscCall(KSPDestroy(&ctx->ksp));
     519           2 :   ctx->ksp   = ksp;
     520           2 :   nep->state = NEP_STATE_INITIAL;
     521           2 :   PetscFunctionReturn(PETSC_SUCCESS);
     522             : }
     523             : 
     524             : /*@
     525             :    NEPSLPSetKSP - Associate a linear solver object (KSP) to the nonlinear
     526             :    eigenvalue solver.
     527             : 
     528             :    Collective
     529             : 
     530             :    Input Parameters:
     531             : +  nep - eigenvalue solver
     532             : -  ksp - the linear solver object
     533             : 
     534             :    Level: advanced
     535             : 
     536             : .seealso: NEPSLPGetKSP()
     537             : @*/
     538           2 : PetscErrorCode NEPSLPSetKSP(NEP nep,KSP ksp)
     539             : {
     540           2 :   PetscFunctionBegin;
     541           2 :   PetscValidHeaderSpecific(nep,NEP_CLASSID,1);
     542           2 :   PetscValidHeaderSpecific(ksp,KSP_CLASSID,2);
     543           2 :   PetscCheckSameComm(nep,1,ksp,2);
     544           2 :   PetscTryMethod(nep,"NEPSLPSetKSP_C",(NEP,KSP),(nep,ksp));
     545           2 :   PetscFunctionReturn(PETSC_SUCCESS);
     546             : }
     547             : 
     548          23 : static PetscErrorCode NEPSLPGetKSP_SLP(NEP nep,KSP *ksp)
     549             : {
     550          23 :   NEP_SLP        *ctx = (NEP_SLP*)nep->data;
     551             : 
     552          23 :   PetscFunctionBegin;
     553          23 :   if (!ctx->ksp) {
     554          23 :     PetscCall(KSPCreate(PetscObjectComm((PetscObject)nep),&ctx->ksp));
     555          23 :     PetscCall(PetscObjectIncrementTabLevel((PetscObject)ctx->ksp,(PetscObject)nep,1));
     556          23 :     PetscCall(KSPSetOptionsPrefix(ctx->ksp,((PetscObject)nep)->prefix));
     557          23 :     PetscCall(KSPAppendOptionsPrefix(ctx->ksp,"nep_slp_"));
     558          23 :     PetscCall(PetscObjectSetOptions((PetscObject)ctx->ksp,((PetscObject)nep)->options));
     559          23 :     PetscCall(KSPSetErrorIfNotConverged(ctx->ksp,PETSC_TRUE));
     560          35 :     PetscCall(KSPSetTolerances(ctx->ksp,SlepcDefaultTol(nep->tol),PETSC_CURRENT,PETSC_CURRENT,PETSC_CURRENT));
     561             :   }
     562          23 :   *ksp = ctx->ksp;
     563          23 :   PetscFunctionReturn(PETSC_SUCCESS);
     564             : }
     565             : 
     566             : /*@
     567             :    NEPSLPGetKSP - Retrieve the linear solver object (KSP) associated with
     568             :    the nonlinear eigenvalue solver.
     569             : 
     570             :    Collective
     571             : 
     572             :    Input Parameter:
     573             : .  nep - nonlinear eigenvalue solver
     574             : 
     575             :    Output Parameter:
     576             : .  ksp - the linear solver object
     577             : 
     578             :    Level: advanced
     579             : 
     580             : .seealso: NEPSLPSetKSP()
     581             : @*/
     582          23 : PetscErrorCode NEPSLPGetKSP(NEP nep,KSP *ksp)
     583             : {
     584          23 :   PetscFunctionBegin;
     585          23 :   PetscValidHeaderSpecific(nep,NEP_CLASSID,1);
     586          23 :   PetscAssertPointer(ksp,2);
     587          23 :   PetscUseMethod(nep,"NEPSLPGetKSP_C",(NEP,KSP*),(nep,ksp));
     588          23 :   PetscFunctionReturn(PETSC_SUCCESS);
     589             : }
     590             : 
     591           1 : static PetscErrorCode NEPView_SLP(NEP nep,PetscViewer viewer)
     592             : {
     593           1 :   NEP_SLP        *ctx = (NEP_SLP*)nep->data;
     594           1 :   PetscBool      isascii;
     595             : 
     596           1 :   PetscFunctionBegin;
     597           1 :   PetscCall(PetscObjectTypeCompare((PetscObject)viewer,PETSCVIEWERASCII,&isascii));
     598           1 :   if (isascii) {
     599           1 :     if (ctx->deftol) PetscCall(PetscViewerASCIIPrintf(viewer,"  deflation threshold: %g\n",(double)ctx->deftol));
     600           1 :     if (!ctx->eps) PetscCall(NEPSLPGetEPS(nep,&ctx->eps));
     601           1 :     PetscCall(PetscViewerASCIIPushTab(viewer));
     602           1 :     PetscCall(EPSView(ctx->eps,viewer));
     603           1 :     if (nep->twosided) {
     604           0 :       if (!ctx->epsts) PetscCall(NEPSLPGetEPSLeft(nep,&ctx->epsts));
     605           0 :       PetscCall(EPSView(ctx->epsts,viewer));
     606             :     }
     607           1 :     if (!ctx->ksp) PetscCall(NEPSLPGetKSP(nep,&ctx->ksp));
     608           1 :     PetscCall(KSPView(ctx->ksp,viewer));
     609           1 :     PetscCall(PetscViewerASCIIPopTab(viewer));
     610             :   }
     611           1 :   PetscFunctionReturn(PETSC_SUCCESS);
     612             : }
     613             : 
     614          29 : static PetscErrorCode NEPReset_SLP(NEP nep)
     615             : {
     616          29 :   NEP_SLP        *ctx = (NEP_SLP*)nep->data;
     617             : 
     618          29 :   PetscFunctionBegin;
     619          29 :   PetscCall(EPSReset(ctx->eps));
     620          29 :   if (nep->twosided) PetscCall(EPSReset(ctx->epsts));
     621          29 :   PetscCall(KSPReset(ctx->ksp));
     622          29 :   PetscFunctionReturn(PETSC_SUCCESS);
     623             : }
     624             : 
     625          25 : static PetscErrorCode NEPDestroy_SLP(NEP nep)
     626             : {
     627          25 :   NEP_SLP        *ctx = (NEP_SLP*)nep->data;
     628             : 
     629          25 :   PetscFunctionBegin;
     630          25 :   PetscCall(KSPDestroy(&ctx->ksp));
     631          25 :   PetscCall(EPSDestroy(&ctx->eps));
     632          25 :   PetscCall(EPSDestroy(&ctx->epsts));
     633          25 :   PetscCall(PetscFree(nep->data));
     634          25 :   PetscCall(PetscObjectComposeFunction((PetscObject)nep,"NEPSLPSetDeflationThreshold_C",NULL));
     635          25 :   PetscCall(PetscObjectComposeFunction((PetscObject)nep,"NEPSLPGetDeflationThreshold_C",NULL));
     636          25 :   PetscCall(PetscObjectComposeFunction((PetscObject)nep,"NEPSLPSetEPS_C",NULL));
     637          25 :   PetscCall(PetscObjectComposeFunction((PetscObject)nep,"NEPSLPGetEPS_C",NULL));
     638          25 :   PetscCall(PetscObjectComposeFunction((PetscObject)nep,"NEPSLPSetEPSLeft_C",NULL));
     639          25 :   PetscCall(PetscObjectComposeFunction((PetscObject)nep,"NEPSLPGetEPSLeft_C",NULL));
     640          25 :   PetscCall(PetscObjectComposeFunction((PetscObject)nep,"NEPSLPSetKSP_C",NULL));
     641          25 :   PetscCall(PetscObjectComposeFunction((PetscObject)nep,"NEPSLPGetKSP_C",NULL));
     642          25 :   PetscFunctionReturn(PETSC_SUCCESS);
     643             : }
     644             : 
     645          25 : SLEPC_EXTERN PetscErrorCode NEPCreate_SLP(NEP nep)
     646             : {
     647          25 :   NEP_SLP        *ctx;
     648             : 
     649          25 :   PetscFunctionBegin;
     650          25 :   PetscCall(PetscNew(&ctx));
     651          25 :   nep->data = (void*)ctx;
     652             : 
     653          25 :   nep->useds  = PETSC_TRUE;
     654          25 :   ctx->deftol = PETSC_DETERMINE;
     655             : 
     656          25 :   nep->ops->solve          = NEPSolve_SLP;
     657          25 :   nep->ops->setup          = NEPSetUp_SLP;
     658          25 :   nep->ops->setfromoptions = NEPSetFromOptions_SLP;
     659          25 :   nep->ops->reset          = NEPReset_SLP;
     660          25 :   nep->ops->destroy        = NEPDestroy_SLP;
     661          25 :   nep->ops->view           = NEPView_SLP;
     662          25 :   nep->ops->computevectors = NEPComputeVectors_Schur;
     663             : 
     664          25 :   PetscCall(PetscObjectComposeFunction((PetscObject)nep,"NEPSLPSetDeflationThreshold_C",NEPSLPSetDeflationThreshold_SLP));
     665          25 :   PetscCall(PetscObjectComposeFunction((PetscObject)nep,"NEPSLPGetDeflationThreshold_C",NEPSLPGetDeflationThreshold_SLP));
     666          25 :   PetscCall(PetscObjectComposeFunction((PetscObject)nep,"NEPSLPSetEPS_C",NEPSLPSetEPS_SLP));
     667          25 :   PetscCall(PetscObjectComposeFunction((PetscObject)nep,"NEPSLPGetEPS_C",NEPSLPGetEPS_SLP));
     668          25 :   PetscCall(PetscObjectComposeFunction((PetscObject)nep,"NEPSLPSetEPSLeft_C",NEPSLPSetEPSLeft_SLP));
     669          25 :   PetscCall(PetscObjectComposeFunction((PetscObject)nep,"NEPSLPGetEPSLeft_C",NEPSLPGetEPSLeft_SLP));
     670          25 :   PetscCall(PetscObjectComposeFunction((PetscObject)nep,"NEPSLPSetKSP_C",NEPSLPSetKSP_SLP));
     671          25 :   PetscCall(PetscObjectComposeFunction((PetscObject)nep,"NEPSLPGetKSP_C",NEPSLPGetKSP_SLP));
     672          25 :   PetscFunctionReturn(PETSC_SUCCESS);
     673             : }

Generated by: LCOV version 1.14