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