Date: 2016-03-29T14:59:20+00:00

Actual source code: rii.c
slepc-3.6.3 2016-03-29
Report Typos and Errors

      1: /*

      3:    SLEPc nonlinear eigensolver: "rii"

      5:    Method: Residual inverse iteration

      7:    Algorithm:

      9:        Simple residual inverse iteration with varying shift.

     11:    References:

     13:        [1] A. Neumaier, "Residual inverse iteration for the nonlinear
     14:            eigenvalue problem", SIAM J. Numer. Anal. 22(5):914-923, 1985.

     16:    - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
     17:    SLEPc - Scalable Library for Eigenvalue Problem Computations
     18:    Copyright (c) 2002-2015, Universitat Politecnica de Valencia, Spain

     20:    This file is part of SLEPc.

     22:    SLEPc is free software: you can redistribute it and/or modify it under  the
     23:    terms of version 3 of the GNU Lesser General Public License as published by
     24:    the Free Software Foundation.

     26:    SLEPc  is  distributed in the hope that it will be useful, but WITHOUT  ANY
     27:    WARRANTY;  without even the implied warranty of MERCHANTABILITY or  FITNESS
     28:    FOR  A  PARTICULAR PURPOSE. See the GNU Lesser General Public  License  for
     29:    more details.

     31:    You  should have received a copy of the GNU Lesser General  Public  License
     32:    along with SLEPc. If not, see <http://www.gnu.org/licenses/>.
     33:    - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
     34: */

     36: #include <slepc/private/nepimpl.h>

     40: PetscErrorCode NEPSetUp_RII(NEP nep)
     41: {
     43:   PetscBool      istrivial;

     46:   if (nep->ncv) { /* ncv set */
     47:     if (nep->ncv<nep->nev) SETERRQ(PetscObjectComm((PetscObject)nep),1,"The value of ncv must be at least nev");
     48:   } else if (nep->mpd) { /* mpd set */
     49:     nep->ncv = PetscMin(nep->n,nep->nev+nep->mpd);
     50:   } else { /* neither set: defaults depend on nev being small or large */
     51:     if (nep->nev<500) nep->ncv = PetscMin(nep->n,PetscMax(2*nep->nev,nep->nev+15));
     52:     else {
     53:       nep->mpd = 500;
     54:       nep->ncv = PetscMin(nep->n,nep->nev+nep->mpd);
     55:     }
     56:   }
     57:   if (!nep->mpd) nep->mpd = nep->ncv;
     58:   if (nep->ncv>nep->nev+nep->mpd) SETERRQ(PetscObjectComm((PetscObject)nep),1,"The value of ncv must not be larger than nev+mpd");
     59:   if (nep->nev>1) { PetscInfo(nep,"Warning: requested more than one eigenpair but RII can only compute one\n"); }
     60:   if (!nep->max_it) nep->max_it = PetscMax(5000,2*nep->n/nep->ncv);
     61:   if (!nep->max_funcs) nep->max_funcs = nep->max_it;

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

     66:   NEPAllocateSolution(nep,0);
     67:   NEPSetWorkVecs(nep,2);
     68:   return(0);
     69: }

     73: PetscErrorCode NEPSolve_RII(NEP nep)
     74: {
     75:   PetscErrorCode     ierr;
     76:   Mat                T=nep->function,Tp=nep->jacobian,Tsigma;
     77:   Vec                u,r=nep->work[0],delta=nep->work[1];
     78:   PetscScalar        lambda,a1,a2;
     79:   PetscReal          relerr;
     80:   PetscBool          hascopy;
     81:   KSPConvergedReason kspreason;

     84:   /* get initial approximation of eigenvalue and eigenvector */
     85:   NEPGetDefaultShift(nep,&lambda);
     86:   if (!nep->nini) {
     87:     BVSetRandomColumn(nep->V,0,nep->rand);
     88:   }
     89:   BVGetColumn(nep->V,0,&u);

     91:   /* correct eigenvalue approximation: lambda = lambda - (u'*T*u)/(u'*Tp*u) */
     92:   NEPComputeFunction(nep,lambda,T,T);
     93:   MatMult(T,u,r);
     94:   VecDot(u,r,&a1);
     95:   NEPApplyJacobian(nep,lambda,u,delta,r,Tp);
     96:   VecDot(u,r,&a2);
     97:   lambda = lambda - a1/a2;

     99:   /* prepare linear solver */
    100:   MatDuplicate(T,MAT_COPY_VALUES,&Tsigma);
    101:   KSPSetOperators(nep->ksp,Tsigma,Tsigma);

    103:   /* Restart loop */
    104:   while (nep->reason == NEP_CONVERGED_ITERATING) {
    105:     nep->its++;

    107:     /* update preconditioner and set adaptive tolerance */
    108:     if (nep->lag && !(nep->its%nep->lag) && nep->its>2*nep->lag && relerr<1e-2) {
    109:       MatHasOperation(T,MATOP_COPY,&hascopy);
    110:       if (hascopy) {
    111:         MatCopy(T,Tsigma,DIFFERENT_NONZERO_PATTERN);
    112:       } else {
    113:         MatDestroy(&Tsigma);
    114:         MatDuplicate(T,MAT_COPY_VALUES,&Tsigma);
    115:       }
    116:       KSPSetOperators(nep->ksp,Tsigma,Tsigma);
    117:     }
    118:     if (!nep->cctol) {
    119:       nep->ktol = PetscMax(nep->ktol/2.0,PETSC_MACHINE_EPSILON*10.0);
    120:       KSPSetTolerances(nep->ksp,nep->ktol,PETSC_DEFAULT,PETSC_DEFAULT,PETSC_DEFAULT);
    121:     }

    123:     /* form residual,  r = T(lambda)*u */
    124:     NEPApplyFunction(nep,lambda,u,delta,r,T,T);

    126:     /* convergence test */
    127:     VecNorm(r,NORM_2,&relerr);
    128:     nep->errest[nep->nconv] = relerr;
    129:     nep->eigr[nep->nconv] = lambda;
    130:     if (relerr<=nep->rtol) {
    131:       nep->nconv = nep->nconv + 1;
    132:       nep->reason = NEP_CONVERGED_FNORM_RELATIVE;
    133:     }
    134:     NEPMonitor(nep,nep->its,nep->nconv,nep->eigr,nep->errest,1);

    136:     if (!nep->nconv) {
    137:       /* eigenvector correction: delta = T(sigma)\r */
    138:       NEP_KSPSolve(nep,r,delta);
    139:       KSPGetConvergedReason(nep->ksp,&kspreason);
    140:       if (kspreason<0) {
    141:         PetscInfo1(nep,"iter=%D, linear solve failed, stopping solve\n",nep->its);
    142:         nep->reason = NEP_DIVERGED_LINEAR_SOLVE;
    143:         break;
    144:       }

    146:       /* update eigenvector: u = u - delta */
    147:       VecAXPY(u,-1.0,delta);

    149:       /* normalize eigenvector */
    150:       VecNormalize(u,NULL);

    152:       /* correct eigenvalue: lambda = lambda - (u'*T*u)/(u'*Tp*u) */
    153:       NEPApplyFunction(nep,lambda,u,delta,r,T,T);
    154:       VecDot(u,r,&a1);
    155:       NEPApplyJacobian(nep,lambda,u,delta,r,Tp);
    156:       VecDot(u,r,&a2);
    157:       lambda = lambda - a1/a2;
    158:     }
    159:     if (nep->its >= nep->max_it) nep->reason = NEP_DIVERGED_MAX_IT;
    160:   }
    161:   MatDestroy(&Tsigma);
    162:   BVRestoreColumn(nep->V,0,&u);
    163:   return(0);
    164: }

    168: PETSC_EXTERN PetscErrorCode NEPCreate_RII(NEP nep)
    169: {
    171:   nep->ops->solve        = NEPSolve_RII;
    172:   nep->ops->setup        = NEPSetUp_RII;
    173:   return(0);
    174: }