Actual source code: rqi.c

  2: /*                       
  3:        This implements the Rayleigh Quotient Iteration method.
  4: */
 5:  #include src/eps/epsimpl.h

  9: static int EPSSetUp_RQI(EPS eps)
 10: {
 11:   int        ierr;
 12:   PetscTruth isSinv;

 15:   PetscTypeCompare((PetscObject)eps->OP,STSINV,&isSinv);
 16:   if (!isSinv) SETERRQ(1,"A shift-and-invert ST must be specified in order to use RQI");
 17:   EPSDefaultGetWork(eps,3);
 18:   return(0);
 19: }

 23: static int EPSSetDefaults_RQI(EPS eps)
 24: {
 25:   int         ierr, N;

 28:   VecGetSize(eps->vec_initial,&N);
 29:   if (eps->ncv) {
 30:     if (eps->ncv<eps->nev) SETERRQ(1,"The value of ncv must be at least nev");
 31:   }
 32:   else eps->ncv = eps->nev;
 33:   if (!eps->max_it) eps->max_it = PetscMax(100,N);
 34:   if (!eps->tol) eps->tol = 1.e-7;
 35:   return(0);
 36: }

 40: static int  EPSSolve_RQI(EPS eps)
 41: {
 42:   int         ierr, i, maxit=eps->max_it;
 43:   Vec         v, w, y, e;
 44:   PetscReal   relerr, tol=1.0/PetscSqrtScalar(eps->tol);
 45:   PetscScalar theta, alpha, eta, rho;

 48:   v = eps->V[0];
 49:   y = eps->work[0];
 50:   w = eps->work[1];
 51:   e = eps->work[2];
 52:   eps->nconv = 0;

 54:   /* initial shift, rho_1 */
 55:   STGetShift(eps->OP,&rho);

 57:   /* w = B v, normalize v so that v^* w = 1 */
 58:   VecCopy(eps->vec_initial,v);
 59:   STApplyB(eps->OP,v,w);
 60:   VecDot(w,v,&eta);
 61: #if !defined(PETSC_USE_COMPLEX)
 62:   if (eta<0.0) SETERRQ(1,"Negative value of eta");
 63: #endif
 64:   eta = PetscSqrtScalar(eta);
 65:   if (eta==0.0) SETERRQ(1,"Zero value of eta");
 66:   alpha = 1.0/eta;
 67:   VecScale(&alpha,v);
 68:   VecScale(&alpha,w);

 70:   for (i=0;i<maxit;i++) {
 71:     eps->its = i;

 73:     /* y = OP w */
 74:     STApplyNoB(eps->OP,w,y);

 76:     /* theta = w^* y */
 77:     VecDot(y,w,&theta);

 79:     /* w = B y */
 80:     STApplyB(eps->OP,y,w);

 82:     /* eta = ||y||_B */
 83:     VecDot(w,y,&eta);
 84: #if !defined(PETSC_USE_COMPLEX)
 85:     if (eta<0.0) SETERRQ(1,"Negative value of eta");
 86: #endif
 87:     eta = PetscSqrtScalar(eta);

 89:     /* normalize y and w */
 90:     VecCopy(y,v);
 91:     alpha = 1.0/eta;
 92:     VecScale(&alpha,v);
 93:     VecScale(&alpha,w);

 95:     /* rho_{k+1} = rho_{k} + theta/eta^2 */
 96:     rho = rho + theta/(eta*eta);
 97:     STSetShift(eps->OP,rho);

 99:     /* if |theta| > tol^-1/2, stop */
100:     relerr = PetscAbsScalar(theta);
101:     eps->errest[eps->nconv] = 1/(relerr*relerr);
102:     EPSMonitorEstimates(eps,i+1,eps->nconv,eps->errest,eps->nconv+1);
103:     eps->eigr[eps->nconv] = rho;
104:     EPSMonitorValues(eps,i+1,eps->nconv,eps->eigr,PETSC_NULL,eps->nconv+1);
105:     if (relerr>tol) {
106:       eps->nconv = eps->nconv + 1;
107:       break;
108:     }

110:   }

112:   if( i==maxit ) i--;
113:   eps->its = i+1;
114:   if( eps->nconv == eps->nev ) eps->reason = EPS_CONVERGED_TOL;
115:   else eps->reason = EPS_DIVERGED_ITS;
116:   for (i=0;i<eps->nconv;i++) eps->eigi[i]=0.0;

118:   return(0);
119: }

121: EXTERN_C_BEGIN
124: int EPSCreate_RQI(EPS eps)
125: {
127:   eps->data                      = (void *) 0;
128:   eps->ops->setup                = EPSSetUp_RQI;
129:   eps->ops->setdefaults          = EPSSetDefaults_RQI;
130:   eps->ops->solve                = EPSSolve_RQI;
131:   eps->ops->destroy              = EPSDefaultDestroy;
132:   eps->ops->view                 = 0;
133:   eps->ops->backtransform        = EPSBackTransform_Default;
134:   return(0);
135: }
136: EXTERN_C_END