LCOV - code coverage report
Current view: top level - nep/impls/rii - rii.c (source / functions) Hit Total Coverage
Test: SLEPc Lines: 368 371 99.2 %
Date: 2024-11-21 00:40:22 Functions: 31 31 100.0 %
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: "rii"
      12             : 
      13             :    Method: Residual inverse iteration
      14             : 
      15             :    Algorithm:
      16             : 
      17             :        Simple residual inverse iteration with varying shift.
      18             : 
      19             :    References:
      20             : 
      21             :        [1] A. Neumaier, "Residual inverse iteration for the nonlinear
      22             :            eigenvalue problem", SIAM J. Numer. Anal. 22(5):914-923, 1985.
      23             : */
      24             : 
      25             : #include <slepc/private/nepimpl.h>         /*I "slepcnep.h" I*/
      26             : #include <../src/nep/impls/nepdefl.h>
      27             : 
      28             : typedef struct {
      29             :   PetscInt  max_inner_it;     /* maximum number of Newton iterations */
      30             :   PetscInt  lag;              /* interval to rebuild preconditioner */
      31             :   PetscBool cctol;            /* constant correction tolerance */
      32             :   PetscBool herm;             /* whether the Hermitian version of the scalar equation must be used */
      33             :   PetscReal deftol;           /* tolerance for the deflation (threshold) */
      34             :   KSP       ksp;              /* linear solver object */
      35             : } NEP_RII;
      36             : 
      37          24 : static PetscErrorCode NEPSetUp_RII(NEP nep)
      38             : {
      39          24 :   PetscFunctionBegin;
      40          24 :   if (nep->ncv!=PETSC_DETERMINE) PetscCall(PetscInfo(nep,"Setting ncv = nev, ignoring user-provided value\n"));
      41          24 :   nep->ncv = nep->nev;
      42          24 :   if (nep->mpd!=PETSC_DETERMINE) PetscCall(PetscInfo(nep,"Setting mpd = nev, ignoring user-provided value\n"));
      43          24 :   nep->mpd = nep->nev;
      44          24 :   if (nep->max_it==PETSC_DETERMINE) nep->max_it = PetscMax(5000,2*nep->n/nep->ncv);
      45          24 :   if (!nep->which) nep->which = NEP_TARGET_MAGNITUDE;
      46          24 :   PetscCheck(nep->which==NEP_TARGET_MAGNITUDE,PetscObjectComm((PetscObject)nep),PETSC_ERR_SUP,"This solver supports only target magnitude eigenvalues");
      47          24 :   NEPCheckUnsupported(nep,NEP_FEATURE_REGION | NEP_FEATURE_TWOSIDED);
      48          24 :   PetscCall(NEPAllocateSolution(nep,0));
      49          24 :   PetscCall(NEPSetWorkVecs(nep,2));
      50          24 :   PetscFunctionReturn(PETSC_SUCCESS);
      51             : }
      52             : 
      53          24 : static PetscErrorCode NEPSolve_RII(NEP nep)
      54             : {
      55          24 :   NEP_RII            *ctx = (NEP_RII*)nep->data;
      56          24 :   Mat                T,Tp,H,A;
      57          24 :   Vec                uu,u,r,delta,t;
      58          24 :   PetscScalar        lambda,lambda2,sigma,a1,a2,corr;
      59          24 :   PetscReal          nrm,resnorm=1.0,ktol=0.1,perr,rtol;
      60          24 :   PetscBool          skip=PETSC_FALSE,lock=PETSC_FALSE;
      61          24 :   PetscInt           inner_its,its=0;
      62          24 :   NEP_EXT_OP         extop=NULL;
      63          24 :   KSPConvergedReason kspreason;
      64             : 
      65          24 :   PetscFunctionBegin;
      66             :   /* get initial approximation of eigenvalue and eigenvector */
      67          24 :   PetscCall(NEPGetDefaultShift(nep,&sigma));
      68          24 :   lambda = sigma;
      69          24 :   if (!nep->nini) {
      70          22 :     PetscCall(BVSetRandomColumn(nep->V,0));
      71          22 :     PetscCall(BVNormColumn(nep->V,0,NORM_2,&nrm));
      72          22 :     PetscCall(BVScaleColumn(nep->V,0,1.0/nrm));
      73             :   }
      74          24 :   if (!ctx->ksp) PetscCall(NEPRIIGetKSP(nep,&ctx->ksp));
      75          24 :   PetscCall(NEPDeflationInitialize(nep,nep->V,ctx->ksp,PETSC_FALSE,nep->nev,&extop));
      76          24 :   PetscCall(NEPDeflationCreateVec(extop,&u));
      77          24 :   PetscCall(VecDuplicate(u,&r));
      78          24 :   PetscCall(VecDuplicate(u,&delta));
      79          24 :   PetscCall(BVGetColumn(nep->V,0,&uu));
      80          24 :   PetscCall(NEPDeflationCopyToExtendedVec(extop,uu,NULL,u,PETSC_FALSE));
      81          24 :   PetscCall(BVRestoreColumn(nep->V,0,&uu));
      82             : 
      83             :   /* prepare linear solver */
      84          24 :   PetscCall(NEPDeflationSolveSetUp(extop,sigma));
      85          24 :   PetscCall(KSPGetTolerances(ctx->ksp,&rtol,NULL,NULL,NULL));
      86             : 
      87          24 :   PetscCall(VecCopy(u,r));
      88          24 :   PetscCall(NEPDeflationFunctionSolve(extop,r,u));
      89          24 :   PetscCall(VecNorm(u,NORM_2,&nrm));
      90          24 :   PetscCall(VecScale(u,1.0/nrm));
      91             : 
      92             :   /* Restart loop */
      93         462 :   while (nep->reason == NEP_CONVERGED_ITERATING) {
      94         438 :     its++;
      95             : 
      96             :     /* Use Newton's method to compute nonlinear Rayleigh functional. Current eigenvalue
      97             :        estimate as starting value. */
      98         438 :     inner_its=0;
      99         438 :     lambda2 = lambda;
     100         916 :     do {
     101         916 :       PetscCall(NEPDeflationComputeFunction(extop,lambda,&T));
     102         916 :       PetscCall(MatMult(T,u,r));
     103         916 :       if (!ctx->herm) {
     104         632 :         PetscCall(NEPDeflationFunctionSolve(extop,r,delta));
     105         632 :         PetscCall(KSPGetConvergedReason(ctx->ksp,&kspreason));
     106         632 :         if (kspreason<0) PetscCall(PetscInfo(nep,"iter=%" PetscInt_FMT ", linear solve failed\n",nep->its));
     107         632 :         t = delta;
     108         284 :       } else t = r;
     109         916 :       PetscCall(VecDot(t,u,&a1));
     110         916 :       PetscCall(NEPDeflationComputeJacobian(extop,lambda,&Tp));
     111         916 :       PetscCall(MatMult(Tp,u,r));
     112         916 :       if (!ctx->herm) {
     113         632 :         PetscCall(NEPDeflationFunctionSolve(extop,r,delta));
     114         632 :         PetscCall(KSPGetConvergedReason(ctx->ksp,&kspreason));
     115         632 :         if (kspreason<0) PetscCall(PetscInfo(nep,"iter=%" PetscInt_FMT ", linear solve failed\n",nep->its));
     116         632 :         t = delta;
     117         284 :       } else t = r;
     118         916 :       PetscCall(VecDot(t,u,&a2));
     119         916 :       corr = a1/a2;
     120         916 :       lambda = lambda - corr;
     121         916 :       inner_its++;
     122         916 :     } while (PetscAbsScalar(corr)/PetscAbsScalar(lambda)>PETSC_SQRT_MACHINE_EPSILON && inner_its<ctx->max_inner_it);
     123             : 
     124             :     /* form residual,  r = T(lambda)*u */
     125         438 :     PetscCall(NEPDeflationComputeFunction(extop,lambda,&T));
     126         438 :     PetscCall(MatMult(T,u,r));
     127             : 
     128             :     /* convergence test */
     129         438 :     perr = nep->errest[nep->nconv];
     130         438 :     PetscCall(VecNorm(r,NORM_2,&resnorm));
     131         438 :     PetscCall((*nep->converged)(nep,lambda,0,resnorm,&nep->errest[nep->nconv],nep->convergedctx));
     132         438 :     nep->eigr[nep->nconv] = lambda;
     133         438 :     if (its>1 && (nep->errest[nep->nconv]<=nep->tol || nep->errest[nep->nconv]<=ctx->deftol)) {
     134          37 :       if (nep->errest[nep->nconv]<=ctx->deftol && !extop->ref && nep->nconv) {
     135           4 :         PetscCall(NEPDeflationExtractEigenpair(extop,nep->nconv,u,lambda,nep->ds));
     136           4 :         PetscCall(NEPDeflationSetRefine(extop,PETSC_TRUE));
     137           4 :         PetscCall(MatMult(T,u,r));
     138           4 :         PetscCall(VecNorm(r,NORM_2,&resnorm));
     139           4 :         PetscCall((*nep->converged)(nep,lambda,0,resnorm,&nep->errest[nep->nconv],nep->convergedctx));
     140           4 :         if (nep->errest[nep->nconv]<=nep->tol) lock = PETSC_TRUE;
     141          33 :       } else if (nep->errest[nep->nconv]<=nep->tol) lock = PETSC_TRUE;
     142             :     }
     143         403 :     if (lock) {
     144          35 :       PetscCall(NEPDeflationSetRefine(extop,PETSC_FALSE));
     145          35 :       nep->nconv = nep->nconv + 1;
     146          35 :       PetscCall(NEPDeflationLocking(extop,u,lambda));
     147          35 :       nep->its += its;
     148          35 :       skip = PETSC_TRUE;
     149          35 :       lock = PETSC_FALSE;
     150             :     }
     151         438 :     PetscCall((*nep->stopping)(nep,nep->its+its,nep->max_it,nep->nconv,nep->nev,&nep->reason,nep->stoppingctx));
     152         438 :     if (!skip || nep->reason>0) PetscCall(NEPMonitor(nep,nep->its+its,nep->nconv,nep->eigr,nep->eigi,nep->errest,(nep->reason>0)?nep->nconv:nep->nconv+1));
     153             : 
     154         438 :     if (nep->reason == NEP_CONVERGED_ITERATING) {
     155         414 :       if (!skip) {
     156             :         /* update preconditioner and set adaptive tolerance */
     157         403 :         if (ctx->lag && !(its%ctx->lag) && its>=2*ctx->lag && perr && nep->errest[nep->nconv]>.5*perr) PetscCall(NEPDeflationSolveSetUp(extop,lambda2));
     158         403 :         if (!ctx->cctol) {
     159         395 :           ktol = PetscMax(ktol/2.0,rtol);
     160         395 :           PetscCall(KSPSetTolerances(ctx->ksp,ktol,PETSC_CURRENT,PETSC_CURRENT,PETSC_CURRENT));
     161             :         }
     162             : 
     163             :         /* eigenvector correction: delta = T(sigma)\r */
     164         403 :         PetscCall(NEPDeflationFunctionSolve(extop,r,delta));
     165         403 :         PetscCall(KSPGetConvergedReason(ctx->ksp,&kspreason));
     166         403 :         if (kspreason<0) {
     167           0 :           PetscCall(PetscInfo(nep,"iter=%" PetscInt_FMT ", linear solve failed, stopping solve\n",nep->its));
     168           0 :           nep->reason = NEP_DIVERGED_LINEAR_SOLVE;
     169           0 :           break;
     170             :         }
     171             : 
     172             :         /* update eigenvector: u = u - delta */
     173         403 :         PetscCall(VecAXPY(u,-1.0,delta));
     174             : 
     175             :         /* normalize eigenvector */
     176         403 :         PetscCall(VecNormalize(u,NULL));
     177             :       } else {
     178          11 :         its = -1;
     179          11 :         PetscCall(NEPDeflationSetRandomVec(extop,u));
     180          11 :         PetscCall(NEPDeflationSolveSetUp(extop,sigma));
     181          11 :         PetscCall(VecCopy(u,r));
     182          11 :         PetscCall(NEPDeflationFunctionSolve(extop,r,u));
     183          11 :         PetscCall(VecNorm(u,NORM_2,&nrm));
     184          11 :         PetscCall(VecScale(u,1.0/nrm));
     185          11 :         lambda = sigma;
     186          11 :         skip = PETSC_FALSE;
     187             :       }
     188             :     }
     189             :   }
     190          24 :   PetscCall(NEPDeflationGetInvariantPair(extop,NULL,&H));
     191          24 :   PetscCall(DSSetType(nep->ds,DSNHEP));
     192          24 :   PetscCall(DSAllocate(nep->ds,PetscMax(nep->nconv,1)));
     193          24 :   PetscCall(DSSetDimensions(nep->ds,nep->nconv,0,nep->nconv));
     194          24 :   PetscCall(DSGetMat(nep->ds,DS_MAT_A,&A));
     195          24 :   PetscCall(MatCopy(H,A,SAME_NONZERO_PATTERN));
     196          24 :   PetscCall(DSRestoreMat(nep->ds,DS_MAT_A,&A));
     197          24 :   PetscCall(MatDestroy(&H));
     198          24 :   PetscCall(DSSolve(nep->ds,nep->eigr,nep->eigi));
     199          24 :   PetscCall(NEPDeflationReset(extop));
     200          24 :   PetscCall(VecDestroy(&u));
     201          24 :   PetscCall(VecDestroy(&r));
     202          24 :   PetscCall(VecDestroy(&delta));
     203          24 :   PetscFunctionReturn(PETSC_SUCCESS);
     204             : }
     205             : 
     206          20 : static PetscErrorCode NEPSetFromOptions_RII(NEP nep,PetscOptionItems *PetscOptionsObject)
     207             : {
     208          20 :   NEP_RII        *ctx = (NEP_RII*)nep->data;
     209          20 :   PetscBool      flg;
     210          20 :   PetscInt       i;
     211          20 :   PetscReal      r;
     212             : 
     213          20 :   PetscFunctionBegin;
     214          20 :   PetscOptionsHeadBegin(PetscOptionsObject,"NEP RII Options");
     215             : 
     216          20 :     i = 0;
     217          20 :     PetscCall(PetscOptionsInt("-nep_rii_max_it","Maximum number of Newton iterations for updating Rayleigh functional","NEPRIISetMaximumIterations",ctx->max_inner_it,&i,&flg));
     218          20 :     if (flg) PetscCall(NEPRIISetMaximumIterations(nep,i));
     219             : 
     220          20 :     PetscCall(PetscOptionsBool("-nep_rii_const_correction_tol","Constant correction tolerance for the linear solver","NEPRIISetConstCorrectionTol",ctx->cctol,&ctx->cctol,NULL));
     221             : 
     222          20 :     PetscCall(PetscOptionsBool("-nep_rii_hermitian","Use Hermitian version of the scalar nonlinear equation","NEPRIISetHermitian",ctx->herm,&ctx->herm,NULL));
     223             : 
     224          20 :     i = 0;
     225          20 :     PetscCall(PetscOptionsInt("-nep_rii_lag_preconditioner","Interval to rebuild preconditioner","NEPRIISetLagPreconditioner",ctx->lag,&i,&flg));
     226          20 :     if (flg) PetscCall(NEPRIISetLagPreconditioner(nep,i));
     227             : 
     228          20 :     r = 0.0;
     229          20 :     PetscCall(PetscOptionsReal("-nep_rii_deflation_threshold","Tolerance used as a threshold for including deflated eigenpairs","NEPRIISetDeflationThreshold",ctx->deftol,&r,&flg));
     230          20 :     if (flg) PetscCall(NEPRIISetDeflationThreshold(nep,r));
     231             : 
     232          20 :   PetscOptionsHeadEnd();
     233             : 
     234          20 :   if (!ctx->ksp) PetscCall(NEPRIIGetKSP(nep,&ctx->ksp));
     235          20 :   PetscCall(KSPSetFromOptions(ctx->ksp));
     236          20 :   PetscFunctionReturn(PETSC_SUCCESS);
     237             : }
     238             : 
     239           1 : static PetscErrorCode NEPRIISetMaximumIterations_RII(NEP nep,PetscInt its)
     240             : {
     241           1 :   NEP_RII *ctx = (NEP_RII*)nep->data;
     242             : 
     243           1 :   PetscFunctionBegin;
     244           1 :   if (its==PETSC_DEFAULT || its==PETSC_DECIDE) ctx->max_inner_it = 10;
     245             :   else {
     246           1 :     PetscCheck(its>0,PETSC_COMM_SELF,PETSC_ERR_ARG_OUTOFRANGE,"Number of iterations must be >0");
     247           1 :     ctx->max_inner_it = its;
     248             :   }
     249           1 :   PetscFunctionReturn(PETSC_SUCCESS);
     250             : }
     251             : 
     252             : /*@
     253             :    NEPRIISetMaximumIterations - Sets the maximum number of inner iterations to be
     254             :    used in the RII solver. These are the Newton iterations related to the computation
     255             :    of the nonlinear Rayleigh functional.
     256             : 
     257             :    Logically Collective
     258             : 
     259             :    Input Parameters:
     260             : +  nep - nonlinear eigenvalue solver
     261             : -  its - maximum inner iterations
     262             : 
     263             :    Level: advanced
     264             : 
     265             : .seealso: NEPRIIGetMaximumIterations()
     266             : @*/
     267           1 : PetscErrorCode NEPRIISetMaximumIterations(NEP nep,PetscInt its)
     268             : {
     269           1 :   PetscFunctionBegin;
     270           1 :   PetscValidHeaderSpecific(nep,NEP_CLASSID,1);
     271           3 :   PetscValidLogicalCollectiveInt(nep,its,2);
     272           1 :   PetscTryMethod(nep,"NEPRIISetMaximumIterations_C",(NEP,PetscInt),(nep,its));
     273           1 :   PetscFunctionReturn(PETSC_SUCCESS);
     274             : }
     275             : 
     276           1 : static PetscErrorCode NEPRIIGetMaximumIterations_RII(NEP nep,PetscInt *its)
     277             : {
     278           1 :   NEP_RII *ctx = (NEP_RII*)nep->data;
     279             : 
     280           1 :   PetscFunctionBegin;
     281           1 :   *its = ctx->max_inner_it;
     282           1 :   PetscFunctionReturn(PETSC_SUCCESS);
     283             : }
     284             : 
     285             : /*@
     286             :    NEPRIIGetMaximumIterations - Gets the maximum number of inner iterations of RII.
     287             : 
     288             :    Not Collective
     289             : 
     290             :    Input Parameter:
     291             : .  nep - nonlinear eigenvalue solver
     292             : 
     293             :    Output Parameter:
     294             : .  its - maximum inner iterations
     295             : 
     296             :    Level: advanced
     297             : 
     298             : .seealso: NEPRIISetMaximumIterations()
     299             : @*/
     300           1 : PetscErrorCode NEPRIIGetMaximumIterations(NEP nep,PetscInt *its)
     301             : {
     302           1 :   PetscFunctionBegin;
     303           1 :   PetscValidHeaderSpecific(nep,NEP_CLASSID,1);
     304           1 :   PetscAssertPointer(its,2);
     305           1 :   PetscUseMethod(nep,"NEPRIIGetMaximumIterations_C",(NEP,PetscInt*),(nep,its));
     306           1 :   PetscFunctionReturn(PETSC_SUCCESS);
     307             : }
     308             : 
     309           7 : static PetscErrorCode NEPRIISetLagPreconditioner_RII(NEP nep,PetscInt lag)
     310             : {
     311           7 :   NEP_RII *ctx = (NEP_RII*)nep->data;
     312             : 
     313           7 :   PetscFunctionBegin;
     314           7 :   PetscCheck(lag>=0,PETSC_COMM_SELF,PETSC_ERR_ARG_OUTOFRANGE,"Lag must be non-negative");
     315           7 :   ctx->lag = lag;
     316           7 :   PetscFunctionReturn(PETSC_SUCCESS);
     317             : }
     318             : 
     319             : /*@
     320             :    NEPRIISetLagPreconditioner - Determines when the preconditioner is rebuilt in the
     321             :    nonlinear solve.
     322             : 
     323             :    Logically Collective
     324             : 
     325             :    Input Parameters:
     326             : +  nep - nonlinear eigenvalue solver
     327             : -  lag - 0 indicates NEVER rebuild, 1 means rebuild every time the Jacobian is
     328             :           computed within the nonlinear iteration, 2 means every second time
     329             :           the Jacobian is built, etc.
     330             : 
     331             :    Options Database Keys:
     332             : .  -nep_rii_lag_preconditioner <lag> - the lag value
     333             : 
     334             :    Notes:
     335             :    The default is 1.
     336             :    The preconditioner is ALWAYS built in the first iteration of a nonlinear solve.
     337             : 
     338             :    Level: intermediate
     339             : 
     340             : .seealso: NEPRIIGetLagPreconditioner()
     341             : @*/
     342          24 : PetscErrorCode NEPRIISetLagPreconditioner(NEP nep,PetscInt lag)
     343             : {
     344          24 :   PetscFunctionBegin;
     345          24 :   PetscValidHeaderSpecific(nep,NEP_CLASSID,1);
     346          72 :   PetscValidLogicalCollectiveInt(nep,lag,2);
     347          24 :   PetscTryMethod(nep,"NEPRIISetLagPreconditioner_C",(NEP,PetscInt),(nep,lag));
     348          24 :   PetscFunctionReturn(PETSC_SUCCESS);
     349             : }
     350             : 
     351           1 : static PetscErrorCode NEPRIIGetLagPreconditioner_RII(NEP nep,PetscInt *lag)
     352             : {
     353           1 :   NEP_RII *ctx = (NEP_RII*)nep->data;
     354             : 
     355           1 :   PetscFunctionBegin;
     356           1 :   *lag = ctx->lag;
     357           1 :   PetscFunctionReturn(PETSC_SUCCESS);
     358             : }
     359             : 
     360             : /*@
     361             :    NEPRIIGetLagPreconditioner - Indicates how often the preconditioner is rebuilt.
     362             : 
     363             :    Not Collective
     364             : 
     365             :    Input Parameter:
     366             : .  nep - nonlinear eigenvalue solver
     367             : 
     368             :    Output Parameter:
     369             : .  lag - the lag parameter
     370             : 
     371             :    Level: intermediate
     372             : 
     373             : .seealso: NEPRIISetLagPreconditioner()
     374             : @*/
     375           1 : PetscErrorCode NEPRIIGetLagPreconditioner(NEP nep,PetscInt *lag)
     376             : {
     377           1 :   PetscFunctionBegin;
     378           1 :   PetscValidHeaderSpecific(nep,NEP_CLASSID,1);
     379           1 :   PetscAssertPointer(lag,2);
     380           1 :   PetscUseMethod(nep,"NEPRIIGetLagPreconditioner_C",(NEP,PetscInt*),(nep,lag));
     381           1 :   PetscFunctionReturn(PETSC_SUCCESS);
     382             : }
     383             : 
     384           1 : static PetscErrorCode NEPRIISetConstCorrectionTol_RII(NEP nep,PetscBool cct)
     385             : {
     386           1 :   NEP_RII *ctx = (NEP_RII*)nep->data;
     387             : 
     388           1 :   PetscFunctionBegin;
     389           1 :   ctx->cctol = cct;
     390           1 :   PetscFunctionReturn(PETSC_SUCCESS);
     391             : }
     392             : 
     393             : /*@
     394             :    NEPRIISetConstCorrectionTol - Sets a flag to keep the tolerance used
     395             :    in the linear solver constant.
     396             : 
     397             :    Logically Collective
     398             : 
     399             :    Input Parameters:
     400             : +  nep - nonlinear eigenvalue solver
     401             : -  cct - a boolean value
     402             : 
     403             :    Options Database Keys:
     404             : .  -nep_rii_const_correction_tol <bool> - set the boolean flag
     405             : 
     406             :    Notes:
     407             :    By default, an exponentially decreasing tolerance is set in the KSP used
     408             :    within the nonlinear iteration, so that each Newton iteration requests
     409             :    better accuracy than the previous one. The constant correction tolerance
     410             :    flag stops this behaviour.
     411             : 
     412             :    Level: intermediate
     413             : 
     414             : .seealso: NEPRIIGetConstCorrectionTol()
     415             : @*/
     416           1 : PetscErrorCode NEPRIISetConstCorrectionTol(NEP nep,PetscBool cct)
     417             : {
     418           1 :   PetscFunctionBegin;
     419           1 :   PetscValidHeaderSpecific(nep,NEP_CLASSID,1);
     420           3 :   PetscValidLogicalCollectiveBool(nep,cct,2);
     421           1 :   PetscTryMethod(nep,"NEPRIISetConstCorrectionTol_C",(NEP,PetscBool),(nep,cct));
     422           1 :   PetscFunctionReturn(PETSC_SUCCESS);
     423             : }
     424             : 
     425           1 : static PetscErrorCode NEPRIIGetConstCorrectionTol_RII(NEP nep,PetscBool *cct)
     426             : {
     427           1 :   NEP_RII *ctx = (NEP_RII*)nep->data;
     428             : 
     429           1 :   PetscFunctionBegin;
     430           1 :   *cct = ctx->cctol;
     431           1 :   PetscFunctionReturn(PETSC_SUCCESS);
     432             : }
     433             : 
     434             : /*@
     435             :    NEPRIIGetConstCorrectionTol - Returns the constant tolerance flag.
     436             : 
     437             :    Not Collective
     438             : 
     439             :    Input Parameter:
     440             : .  nep - nonlinear eigenvalue solver
     441             : 
     442             :    Output Parameter:
     443             : .  cct - the value of the constant tolerance flag
     444             : 
     445             :    Level: intermediate
     446             : 
     447             : .seealso: NEPRIISetConstCorrectionTol()
     448             : @*/
     449           1 : PetscErrorCode NEPRIIGetConstCorrectionTol(NEP nep,PetscBool *cct)
     450             : {
     451           1 :   PetscFunctionBegin;
     452           1 :   PetscValidHeaderSpecific(nep,NEP_CLASSID,1);
     453           1 :   PetscAssertPointer(cct,2);
     454           1 :   PetscUseMethod(nep,"NEPRIIGetConstCorrectionTol_C",(NEP,PetscBool*),(nep,cct));
     455           1 :   PetscFunctionReturn(PETSC_SUCCESS);
     456             : }
     457             : 
     458           1 : static PetscErrorCode NEPRIISetHermitian_RII(NEP nep,PetscBool herm)
     459             : {
     460           1 :   NEP_RII *ctx = (NEP_RII*)nep->data;
     461             : 
     462           1 :   PetscFunctionBegin;
     463           1 :   ctx->herm = herm;
     464           1 :   PetscFunctionReturn(PETSC_SUCCESS);
     465             : }
     466             : 
     467             : /*@
     468             :    NEPRIISetHermitian - Sets a flag to indicate if the Hermitian version of the
     469             :    scalar nonlinear equation must be used by the solver.
     470             : 
     471             :    Logically Collective
     472             : 
     473             :    Input Parameters:
     474             : +  nep  - nonlinear eigenvalue solver
     475             : -  herm - a boolean value
     476             : 
     477             :    Options Database Keys:
     478             : .  -nep_rii_hermitian <bool> - set the boolean flag
     479             : 
     480             :    Notes:
     481             :    By default, the scalar nonlinear equation x'*inv(T(sigma))*T(z)*x=0 is solved
     482             :    at each step of the nonlinear iteration. When this flag is set the simpler
     483             :    form x'*T(z)*x=0 is used, which is supposed to be valid only for Hermitian
     484             :    problems.
     485             : 
     486             :    Level: intermediate
     487             : 
     488             : .seealso: NEPRIIGetHermitian()
     489             : @*/
     490           1 : PetscErrorCode NEPRIISetHermitian(NEP nep,PetscBool herm)
     491             : {
     492           1 :   PetscFunctionBegin;
     493           1 :   PetscValidHeaderSpecific(nep,NEP_CLASSID,1);
     494           3 :   PetscValidLogicalCollectiveBool(nep,herm,2);
     495           1 :   PetscTryMethod(nep,"NEPRIISetHermitian_C",(NEP,PetscBool),(nep,herm));
     496           1 :   PetscFunctionReturn(PETSC_SUCCESS);
     497             : }
     498             : 
     499           1 : static PetscErrorCode NEPRIIGetHermitian_RII(NEP nep,PetscBool *herm)
     500             : {
     501           1 :   NEP_RII *ctx = (NEP_RII*)nep->data;
     502             : 
     503           1 :   PetscFunctionBegin;
     504           1 :   *herm = ctx->herm;
     505           1 :   PetscFunctionReturn(PETSC_SUCCESS);
     506             : }
     507             : 
     508             : /*@
     509             :    NEPRIIGetHermitian - Returns the flag about using the Hermitian version of
     510             :    the scalar nonlinear equation.
     511             : 
     512             :    Not Collective
     513             : 
     514             :    Input Parameter:
     515             : .  nep - nonlinear eigenvalue solver
     516             : 
     517             :    Output Parameter:
     518             : .  herm - the value of the hermitian flag
     519             : 
     520             :    Level: intermediate
     521             : 
     522             : .seealso: NEPRIISetHermitian()
     523             : @*/
     524           1 : PetscErrorCode NEPRIIGetHermitian(NEP nep,PetscBool *herm)
     525             : {
     526           1 :   PetscFunctionBegin;
     527           1 :   PetscValidHeaderSpecific(nep,NEP_CLASSID,1);
     528           1 :   PetscAssertPointer(herm,2);
     529           1 :   PetscUseMethod(nep,"NEPRIIGetHermitian_C",(NEP,PetscBool*),(nep,herm));
     530           1 :   PetscFunctionReturn(PETSC_SUCCESS);
     531             : }
     532             : 
     533           2 : static PetscErrorCode NEPRIISetDeflationThreshold_RII(NEP nep,PetscReal deftol)
     534             : {
     535           2 :   NEP_RII *ctx = (NEP_RII*)nep->data;
     536             : 
     537           2 :   PetscFunctionBegin;
     538           2 :   ctx->deftol = deftol;
     539           2 :   PetscFunctionReturn(PETSC_SUCCESS);
     540             : }
     541             : 
     542             : /*@
     543             :    NEPRIISetDeflationThreshold - Sets the threshold value used to switch between
     544             :    deflated and non-deflated iteration.
     545             : 
     546             :    Logically Collective
     547             : 
     548             :    Input Parameters:
     549             : +  nep    - nonlinear eigenvalue solver
     550             : -  deftol - the threshold value
     551             : 
     552             :    Options Database Keys:
     553             : .  -nep_rii_deflation_threshold <deftol> - set the threshold
     554             : 
     555             :    Notes:
     556             :    Normally, the solver iterates on the extended problem in order to deflate
     557             :    previously converged eigenpairs. If this threshold is set to a nonzero value,
     558             :    then once the residual error is below this threshold the solver will
     559             :    continue the iteration without deflation. The intention is to be able to
     560             :    improve the current eigenpair further, despite having previous eigenpairs
     561             :    with somewhat bad precision.
     562             : 
     563             :    Level: advanced
     564             : 
     565             : .seealso: NEPRIIGetDeflationThreshold()
     566             : @*/
     567           2 : PetscErrorCode NEPRIISetDeflationThreshold(NEP nep,PetscReal deftol)
     568             : {
     569           2 :   PetscFunctionBegin;
     570           2 :   PetscValidHeaderSpecific(nep,NEP_CLASSID,1);
     571           6 :   PetscValidLogicalCollectiveReal(nep,deftol,2);
     572           2 :   PetscTryMethod(nep,"NEPRIISetDeflationThreshold_C",(NEP,PetscReal),(nep,deftol));
     573           2 :   PetscFunctionReturn(PETSC_SUCCESS);
     574             : }
     575             : 
     576           1 : static PetscErrorCode NEPRIIGetDeflationThreshold_RII(NEP nep,PetscReal *deftol)
     577             : {
     578           1 :   NEP_RII *ctx = (NEP_RII*)nep->data;
     579             : 
     580           1 :   PetscFunctionBegin;
     581           1 :   *deftol = ctx->deftol;
     582           1 :   PetscFunctionReturn(PETSC_SUCCESS);
     583             : }
     584             : 
     585             : /*@
     586             :    NEPRIIGetDeflationThreshold - Returns the threshold value that controls deflation.
     587             : 
     588             :    Not Collective
     589             : 
     590             :    Input Parameter:
     591             : .  nep - nonlinear eigenvalue solver
     592             : 
     593             :    Output Parameter:
     594             : .  deftol - the threshold
     595             : 
     596             :    Level: advanced
     597             : 
     598             : .seealso: NEPRIISetDeflationThreshold()
     599             : @*/
     600           1 : PetscErrorCode NEPRIIGetDeflationThreshold(NEP nep,PetscReal *deftol)
     601             : {
     602           1 :   PetscFunctionBegin;
     603           1 :   PetscValidHeaderSpecific(nep,NEP_CLASSID,1);
     604           1 :   PetscAssertPointer(deftol,2);
     605           1 :   PetscUseMethod(nep,"NEPRIIGetDeflationThreshold_C",(NEP,PetscReal*),(nep,deftol));
     606           1 :   PetscFunctionReturn(PETSC_SUCCESS);
     607             : }
     608             : 
     609           1 : static PetscErrorCode NEPRIISetKSP_RII(NEP nep,KSP ksp)
     610             : {
     611           1 :   NEP_RII        *ctx = (NEP_RII*)nep->data;
     612             : 
     613           1 :   PetscFunctionBegin;
     614           1 :   PetscCall(PetscObjectReference((PetscObject)ksp));
     615           1 :   PetscCall(KSPDestroy(&ctx->ksp));
     616           1 :   ctx->ksp = ksp;
     617           1 :   nep->state = NEP_STATE_INITIAL;
     618           1 :   PetscFunctionReturn(PETSC_SUCCESS);
     619             : }
     620             : 
     621             : /*@
     622             :    NEPRIISetKSP - Associate a linear solver object (KSP) to the nonlinear
     623             :    eigenvalue solver.
     624             : 
     625             :    Collective
     626             : 
     627             :    Input Parameters:
     628             : +  nep - eigenvalue solver
     629             : -  ksp - the linear solver object
     630             : 
     631             :    Level: advanced
     632             : 
     633             : .seealso: NEPRIIGetKSP()
     634             : @*/
     635           1 : PetscErrorCode NEPRIISetKSP(NEP nep,KSP ksp)
     636             : {
     637           1 :   PetscFunctionBegin;
     638           1 :   PetscValidHeaderSpecific(nep,NEP_CLASSID,1);
     639           1 :   PetscValidHeaderSpecific(ksp,KSP_CLASSID,2);
     640           1 :   PetscCheckSameComm(nep,1,ksp,2);
     641           1 :   PetscTryMethod(nep,"NEPRIISetKSP_C",(NEP,KSP),(nep,ksp));
     642           1 :   PetscFunctionReturn(PETSC_SUCCESS);
     643             : }
     644             : 
     645          22 : static PetscErrorCode NEPRIIGetKSP_RII(NEP nep,KSP *ksp)
     646             : {
     647          22 :   NEP_RII        *ctx = (NEP_RII*)nep->data;
     648             : 
     649          22 :   PetscFunctionBegin;
     650          22 :   if (!ctx->ksp) {
     651          22 :     PetscCall(KSPCreate(PetscObjectComm((PetscObject)nep),&ctx->ksp));
     652          22 :     PetscCall(PetscObjectIncrementTabLevel((PetscObject)ctx->ksp,(PetscObject)nep,1));
     653          22 :     PetscCall(KSPSetOptionsPrefix(ctx->ksp,((PetscObject)nep)->prefix));
     654          22 :     PetscCall(KSPAppendOptionsPrefix(ctx->ksp,"nep_rii_"));
     655          22 :     PetscCall(PetscObjectSetOptions((PetscObject)ctx->ksp,((PetscObject)nep)->options));
     656          22 :     PetscCall(KSPSetErrorIfNotConverged(ctx->ksp,PETSC_TRUE));
     657          31 :     PetscCall(KSPSetTolerances(ctx->ksp,SlepcDefaultTol(nep->tol),PETSC_CURRENT,PETSC_CURRENT,PETSC_CURRENT));
     658             :   }
     659          22 :   *ksp = ctx->ksp;
     660          22 :   PetscFunctionReturn(PETSC_SUCCESS);
     661             : }
     662             : 
     663             : /*@
     664             :    NEPRIIGetKSP - Retrieve the linear solver object (KSP) associated with
     665             :    the nonlinear eigenvalue solver.
     666             : 
     667             :    Collective
     668             : 
     669             :    Input Parameter:
     670             : .  nep - nonlinear eigenvalue solver
     671             : 
     672             :    Output Parameter:
     673             : .  ksp - the linear solver object
     674             : 
     675             :    Level: advanced
     676             : 
     677             : .seealso: NEPRIISetKSP()
     678             : @*/
     679          22 : PetscErrorCode NEPRIIGetKSP(NEP nep,KSP *ksp)
     680             : {
     681          22 :   PetscFunctionBegin;
     682          22 :   PetscValidHeaderSpecific(nep,NEP_CLASSID,1);
     683          22 :   PetscAssertPointer(ksp,2);
     684          22 :   PetscUseMethod(nep,"NEPRIIGetKSP_C",(NEP,KSP*),(nep,ksp));
     685          22 :   PetscFunctionReturn(PETSC_SUCCESS);
     686             : }
     687             : 
     688           1 : static PetscErrorCode NEPView_RII(NEP nep,PetscViewer viewer)
     689             : {
     690           1 :   NEP_RII        *ctx = (NEP_RII*)nep->data;
     691           1 :   PetscBool      isascii;
     692             : 
     693           1 :   PetscFunctionBegin;
     694           1 :   PetscCall(PetscObjectTypeCompare((PetscObject)viewer,PETSCVIEWERASCII,&isascii));
     695           1 :   if (isascii) {
     696           1 :     PetscCall(PetscViewerASCIIPrintf(viewer,"  maximum number of inner iterations: %" PetscInt_FMT "\n",ctx->max_inner_it));
     697           1 :     if (ctx->cctol) PetscCall(PetscViewerASCIIPrintf(viewer,"  using a constant tolerance for the linear solver\n"));
     698           1 :     if (ctx->herm) PetscCall(PetscViewerASCIIPrintf(viewer,"  using the Hermitian version of the scalar nonlinear equation\n"));
     699           1 :     if (ctx->lag) PetscCall(PetscViewerASCIIPrintf(viewer,"  updating the preconditioner every %" PetscInt_FMT " iterations\n",ctx->lag));
     700           1 :     if (ctx->deftol) PetscCall(PetscViewerASCIIPrintf(viewer,"  deflation threshold: %g\n",(double)ctx->deftol));
     701           1 :     if (!ctx->ksp) PetscCall(NEPRIIGetKSP(nep,&ctx->ksp));
     702           1 :     PetscCall(PetscViewerASCIIPushTab(viewer));
     703           1 :     PetscCall(KSPView(ctx->ksp,viewer));
     704           1 :     PetscCall(PetscViewerASCIIPopTab(viewer));
     705             :   }
     706           1 :   PetscFunctionReturn(PETSC_SUCCESS);
     707             : }
     708             : 
     709          24 : static PetscErrorCode NEPReset_RII(NEP nep)
     710             : {
     711          24 :   NEP_RII        *ctx = (NEP_RII*)nep->data;
     712             : 
     713          24 :   PetscFunctionBegin;
     714          24 :   PetscCall(KSPReset(ctx->ksp));
     715          24 :   PetscFunctionReturn(PETSC_SUCCESS);
     716             : }
     717             : 
     718          23 : static PetscErrorCode NEPDestroy_RII(NEP nep)
     719             : {
     720          23 :   NEP_RII        *ctx = (NEP_RII*)nep->data;
     721             : 
     722          23 :   PetscFunctionBegin;
     723          23 :   PetscCall(KSPDestroy(&ctx->ksp));
     724          23 :   PetscCall(PetscFree(nep->data));
     725          23 :   PetscCall(PetscObjectComposeFunction((PetscObject)nep,"NEPRIISetMaximumIterations_C",NULL));
     726          23 :   PetscCall(PetscObjectComposeFunction((PetscObject)nep,"NEPRIIGetMaximumIterations_C",NULL));
     727          23 :   PetscCall(PetscObjectComposeFunction((PetscObject)nep,"NEPRIISetLagPreconditioner_C",NULL));
     728          23 :   PetscCall(PetscObjectComposeFunction((PetscObject)nep,"NEPRIIGetLagPreconditioner_C",NULL));
     729          23 :   PetscCall(PetscObjectComposeFunction((PetscObject)nep,"NEPRIISetConstCorrectionTol_C",NULL));
     730          23 :   PetscCall(PetscObjectComposeFunction((PetscObject)nep,"NEPRIIGetConstCorrectionTol_C",NULL));
     731          23 :   PetscCall(PetscObjectComposeFunction((PetscObject)nep,"NEPRIISetHermitian_C",NULL));
     732          23 :   PetscCall(PetscObjectComposeFunction((PetscObject)nep,"NEPRIIGetHermitian_C",NULL));
     733          23 :   PetscCall(PetscObjectComposeFunction((PetscObject)nep,"NEPRIISetDeflationThreshold_C",NULL));
     734          23 :   PetscCall(PetscObjectComposeFunction((PetscObject)nep,"NEPRIIGetDeflationThreshold_C",NULL));
     735          23 :   PetscCall(PetscObjectComposeFunction((PetscObject)nep,"NEPRIISetKSP_C",NULL));
     736          23 :   PetscCall(PetscObjectComposeFunction((PetscObject)nep,"NEPRIIGetKSP_C",NULL));
     737          23 :   PetscFunctionReturn(PETSC_SUCCESS);
     738             : }
     739             : 
     740          23 : SLEPC_EXTERN PetscErrorCode NEPCreate_RII(NEP nep)
     741             : {
     742          23 :   NEP_RII        *ctx;
     743             : 
     744          23 :   PetscFunctionBegin;
     745          23 :   PetscCall(PetscNew(&ctx));
     746          23 :   nep->data = (void*)ctx;
     747          23 :   ctx->max_inner_it = 10;
     748          23 :   ctx->lag          = 1;
     749          23 :   ctx->cctol        = PETSC_FALSE;
     750          23 :   ctx->herm         = PETSC_FALSE;
     751          23 :   ctx->deftol       = 0.0;
     752             : 
     753          23 :   nep->useds = PETSC_TRUE;
     754             : 
     755          23 :   nep->ops->solve          = NEPSolve_RII;
     756          23 :   nep->ops->setup          = NEPSetUp_RII;
     757          23 :   nep->ops->setfromoptions = NEPSetFromOptions_RII;
     758          23 :   nep->ops->reset          = NEPReset_RII;
     759          23 :   nep->ops->destroy        = NEPDestroy_RII;
     760          23 :   nep->ops->view           = NEPView_RII;
     761          23 :   nep->ops->computevectors = NEPComputeVectors_Schur;
     762             : 
     763          23 :   PetscCall(PetscObjectComposeFunction((PetscObject)nep,"NEPRIISetMaximumIterations_C",NEPRIISetMaximumIterations_RII));
     764          23 :   PetscCall(PetscObjectComposeFunction((PetscObject)nep,"NEPRIIGetMaximumIterations_C",NEPRIIGetMaximumIterations_RII));
     765          23 :   PetscCall(PetscObjectComposeFunction((PetscObject)nep,"NEPRIISetLagPreconditioner_C",NEPRIISetLagPreconditioner_RII));
     766          23 :   PetscCall(PetscObjectComposeFunction((PetscObject)nep,"NEPRIIGetLagPreconditioner_C",NEPRIIGetLagPreconditioner_RII));
     767          23 :   PetscCall(PetscObjectComposeFunction((PetscObject)nep,"NEPRIISetConstCorrectionTol_C",NEPRIISetConstCorrectionTol_RII));
     768          23 :   PetscCall(PetscObjectComposeFunction((PetscObject)nep,"NEPRIIGetConstCorrectionTol_C",NEPRIIGetConstCorrectionTol_RII));
     769          23 :   PetscCall(PetscObjectComposeFunction((PetscObject)nep,"NEPRIISetHermitian_C",NEPRIISetHermitian_RII));
     770          23 :   PetscCall(PetscObjectComposeFunction((PetscObject)nep,"NEPRIIGetHermitian_C",NEPRIIGetHermitian_RII));
     771          23 :   PetscCall(PetscObjectComposeFunction((PetscObject)nep,"NEPRIISetDeflationThreshold_C",NEPRIISetDeflationThreshold_RII));
     772          23 :   PetscCall(PetscObjectComposeFunction((PetscObject)nep,"NEPRIIGetDeflationThreshold_C",NEPRIIGetDeflationThreshold_RII));
     773          23 :   PetscCall(PetscObjectComposeFunction((PetscObject)nep,"NEPRIISetKSP_C",NEPRIISetKSP_RII));
     774          23 :   PetscCall(PetscObjectComposeFunction((PetscObject)nep,"NEPRIIGetKSP_C",NEPRIIGetKSP_RII));
     775          23 :   PetscFunctionReturn(PETSC_SUCCESS);
     776             : }

Generated by: LCOV version 1.14