Subversion Repositories slepc-dev

Rev

Details | Compare with Previous | Last modification | View Log | RSS feed

Rev Author Line No. Line
531 dsic.upv.es!jroman 1
/*                      
6 dsic.upv.es!jroman 2
 
531 dsic.upv.es!jroman 3
   SLEPc eigensolver: "power"
4
 
5
   Method: Power Iteration
6
 
953 dsic.upv.es!jroman 7
   Algorithm:
531 dsic.upv.es!jroman 8
 
9
       This solver implements the power iteration for finding dominant
10
       eigenpairs. It also includes the following well-known methods:
11
       - Inverse Iteration: when used in combination with shift-and-invert
12
         spectral transformation.
13
       - Rayleigh Quotient Iteration (RQI): also with shift-and-invert plus
14
         a variable shift.
15
 
16
   References:
17
 
953 dsic.upv.es!jroman 18
       [1] "Single Vector Iteration Methods in SLEPc", SLEPc Technical Report STR-2,
19
           available at http://www.grycap.upv.es/slepc.
531 dsic.upv.es!jroman 20
 
1673 slepc 21
   Last update: Feb 2009
531 dsic.upv.es!jroman 22
 
1376 slepc 23
   - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
1672 slepc 24
   SLEPc - Scalable Library for Eigenvalue Problem Computations
2116 eromero 25
   Copyright (c) 2002-2010, Universidad Politecnica de Valencia, Spain
1376 slepc 26
 
1672 slepc 27
   This file is part of SLEPc.
28
 
29
   SLEPc is free software: you can redistribute it and/or modify it under  the
30
   terms of version 3 of the GNU Lesser General Public License as published by
31
   the Free Software Foundation.
32
 
33
   SLEPc  is  distributed in the hope that it will be useful, but WITHOUT  ANY
34
   WARRANTY;  without even the implied warranty of MERCHANTABILITY or  FITNESS
35
   FOR  A  PARTICULAR PURPOSE. See the GNU Lesser General Public  License  for
36
   more details.
37
 
38
   You  should have received a copy of the GNU Lesser General  Public  License
39
   along with SLEPc. If not, see <http://www.gnu.org/licenses/>.
1376 slepc 40
   - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
6 dsic.upv.es!jroman 41
*/
1376 slepc 42
 
1521 slepc 43
#include "private/epsimpl.h"                /*I "slepceps.h" I*/
444 dsic.upv.es!antodo 44
#include "slepcblaslapack.h"
6 dsic.upv.es!jroman 45
 
1947 jroman 46
PetscErrorCode EPSSolve_POWER(EPS);
47
PetscErrorCode EPSSolve_TS_POWER(EPS);
48
 
444 dsic.upv.es!antodo 49
typedef struct {
50
  EPSPowerShiftType shift_type;
51
} EPS_POWER;
52
 
6 dsic.upv.es!jroman 53
#undef __FUNCT__  
54
#define __FUNCT__ "EPSSetUp_POWER"
476 dsic.upv.es!antodo 55
PetscErrorCode EPSSetUp_POWER(EPS eps)
6 dsic.upv.es!jroman 56
{
476 dsic.upv.es!antodo 57
  PetscErrorCode ierr;
58
  EPS_POWER      *power = (EPS_POWER *)eps->data;
59
  PetscTruth     flg;
60
  STMatMode      mode;
6 dsic.upv.es!jroman 61
 
62
  PetscFunctionBegin;
63
  if (eps->ncv) {
64
    if (eps->ncv<eps->nev) SETERRQ(1,"The value of ncv must be at least nev");
65
  }
66
  else eps->ncv = eps->nev;
1579 slepc 67
  if (eps->mpd) PetscInfo(eps,"Warning: parameter mpd ignored\n");
1928 jroman 68
  if (!eps->max_it) eps->max_it = PetscMax(2000,100*eps->n);
1942 jroman 69
  if (!eps->which) eps->which = EPS_LARGEST_MAGNITUDE;
259 dsic.upv.es!antodo 70
  if (eps->which!=EPS_LARGEST_MAGNITUDE)
71
    SETERRQ(1,"Wrong value of eps->which");
1940 jroman 72
  if (power->shift_type != EPS_POWER_SHIFT_CONSTANT) {
2092 jroman 73
    ierr = PetscTypeCompare((PetscObject)eps->OP,STSINVERT,&flg);CHKERRQ(ierr);
819 dsic.upv.es!jroman 74
    if (!flg)
75
      SETERRQ(PETSC_ERR_SUP,"Variable shifts only allowed in shift-and-invert ST");
444 dsic.upv.es!antodo 76
    ierr = STGetMatMode(eps->OP,&mode);CHKERRQ(ierr);
1940 jroman 77
    if (mode == ST_MATMODE_INPLACE)
444 dsic.upv.es!antodo 78
      SETERRQ(PETSC_ERR_SUP,"ST matrix mode inplace does not work with variable shifts");
79
  }
1560 slepc 80
  if (eps->extraction) {
81
     ierr = PetscInfo(eps,"Warning: extraction type ignored\n");CHKERRQ(ierr);
1426 slepc 82
  }
1940 jroman 83
  if (eps->balance!=EPS_BALANCE_NONE)
1819 jroman 84
    SETERRQ(PETSC_ERR_SUP,"Balancing not supported in this solver");
259 dsic.upv.es!antodo 85
  ierr = EPSAllocateSolution(eps);CHKERRQ(ierr);
1947 jroman 86
  if (eps->leftvecs) {
1937 jroman 87
    ierr = EPSDefaultGetWork(eps,3);CHKERRQ(ierr);
88
  } else {
89
    ierr = EPSDefaultGetWork(eps,2);CHKERRQ(ierr);
90
  }
1947 jroman 91
 
92
  /* dispatch solve method */
93
  if (eps->leftvecs) eps->ops->solve = EPSSolve_TS_POWER;
94
  else eps->ops->solve = EPSSolve_POWER;
6 dsic.upv.es!jroman 95
  PetscFunctionReturn(0);
96
}
97
 
98
#undef __FUNCT__  
99
#define __FUNCT__ "EPSSolve_POWER"
476 dsic.upv.es!antodo 100
PetscErrorCode EPSSolve_POWER(EPS eps)
6 dsic.upv.es!jroman 101
{
476 dsic.upv.es!antodo 102
  PetscErrorCode ierr;
103
  EPS_POWER      *power = (EPS_POWER *)eps->data;
1755 antodo 104
  PetscInt       i;
105
  Vec            v, y, e;
819 dsic.upv.es!jroman 106
  Mat            A;
107
  PetscReal      relerr, norm, rt1, rt2, cs1, anorm;
828 dsic.upv.es!antodo 108
  PetscScalar    theta, rho, delta, sigma, alpha2, beta1, sn1;
1761 antodo 109
  PetscTruth     breakdown,*select = PETSC_NULL,hasnorm;
6 dsic.upv.es!jroman 110
 
111
  PetscFunctionBegin;
112
  v = eps->V[0];
1755 antodo 113
  y = eps->work[1];
428 dsic.upv.es!jroman 114
  e = eps->work[0];
6 dsic.upv.es!jroman 115
 
819 dsic.upv.es!jroman 116
  /* prepare for selective orthogonalization of converged vectors */
1940 jroman 117
  if (power->shift_type != EPS_POWER_SHIFT_CONSTANT && eps->nev>1) {
1761 antodo 118
    ierr = STGetOperators(eps->OP,&A,PETSC_NULL);CHKERRQ(ierr);
119
    ierr = MatHasOperation(A,MATOP_NORM,&hasnorm);CHKERRQ(ierr);
120
    if (hasnorm) {
819 dsic.upv.es!jroman 121
      ierr = MatNorm(A,NORM_INFINITY,&anorm);CHKERRQ(ierr);
1761 antodo 122
      ierr = PetscMalloc(eps->nev*sizeof(PetscTruth),&select);CHKERRQ(ierr);
819 dsic.upv.es!jroman 123
    }
124
  }
6 dsic.upv.es!jroman 125
 
1057 slepc 126
  ierr = EPSGetStartVector(eps,0,v,PETSC_NULL);CHKERRQ(ierr);
819 dsic.upv.es!jroman 127
  ierr = STGetShift(eps->OP,&sigma);CHKERRQ(ierr);    /* original shift */
833 dsic.upv.es!antodo 128
  rho = sigma;
819 dsic.upv.es!jroman 129
 
1057 slepc 130
  while (eps->reason == EPS_CONVERGED_ITERATING) {
1220 slepc 131
    eps->its = eps->its + 1;
252 dsic.upv.es!jroman 132
 
819 dsic.upv.es!jroman 133
    /* y = OP v */
134
    ierr = STApply(eps->OP,v,y);CHKERRQ(ierr);
450 dsic.upv.es!antodo 135
 
819 dsic.upv.es!jroman 136
    /* theta = (v,y)_B */
1345 slepc 137
    ierr = IPInnerProduct(eps->ip,v,y,&theta);CHKERRQ(ierr);
819 dsic.upv.es!jroman 138
 
1940 jroman 139
    if (power->shift_type == EPS_POWER_SHIFT_CONSTANT) { /* direct & inverse iteration */
819 dsic.upv.es!jroman 140
 
141
      /* approximate eigenvalue is the Rayleigh quotient */
142
      eps->eigr[eps->nconv] = theta;
143
 
144
      /* compute relative error as ||y-theta v||_2/|theta| */
145
      ierr = VecCopy(y,e);CHKERRQ(ierr);
828 dsic.upv.es!antodo 146
      ierr = VecAXPY(e,-theta,v);CHKERRQ(ierr);
819 dsic.upv.es!jroman 147
      ierr = VecNorm(e,NORM_2,&norm);CHKERRQ(ierr);
148
      relerr = norm / PetscAbsScalar(theta);
149
 
150
    } else {  /* RQI */
151
 
152
      /* delta = ||y||_B */
1345 slepc 153
      ierr = IPNorm(eps->ip,y,&norm);CHKERRQ(ierr);
819 dsic.upv.es!jroman 154
      delta = norm;
155
 
156
      /* compute relative error */
833 dsic.upv.es!antodo 157
      if (rho == 0.0) relerr = PETSC_MAX;
158
      else relerr = 1.0 / (norm*PetscAbsScalar(rho));
819 dsic.upv.es!jroman 159
 
160
      /* approximate eigenvalue is the shift */
161
      eps->eigr[eps->nconv] = rho;
162
 
163
      /* compute new shift */
833 dsic.upv.es!antodo 164
      if (relerr<eps->tol) {
165
        rho = sigma; /* if converged, restore original shift */
166
        ierr = STSetShift(eps->OP,rho);CHKERRQ(ierr);
167
      } else {
819 dsic.upv.es!jroman 168
        rho = rho + theta/(delta*delta);  /* Rayleigh quotient R(v) */
1940 jroman 169
        if (power->shift_type == EPS_POWER_SHIFT_WILKINSON) {
1062 slepc 170
#if defined(SLEPC_MISSING_LAPACK_LAEV2)
819 dsic.upv.es!jroman 171
          SETERRQ(PETSC_ERR_SUP,"LAEV2 - Lapack routine is unavailable.");
172
#else
173
          /* beta1 is the norm of the residual associated to R(v) */
828 dsic.upv.es!antodo 174
          ierr = VecAXPY(v,-theta/(delta*delta),y);CHKERRQ(ierr);
175
          ierr = VecScale(v,1.0/delta);CHKERRQ(ierr);
1345 slepc 176
          ierr = IPNorm(eps->ip,v,&norm);CHKERRQ(ierr);
819 dsic.upv.es!jroman 177
          beta1 = norm;
178
 
179
          /* alpha2 = (e'*A*e)/(beta1*beta1), where e is the residual */
180
          ierr = STGetOperators(eps->OP,&A,PETSC_NULL);CHKERRQ(ierr);
181
          ierr = MatMult(A,v,e);CHKERRQ(ierr);
182
          ierr = VecDot(v,e,&alpha2);CHKERRQ(ierr);
183
          alpha2 = alpha2 / (beta1 * beta1);
184
 
185
          /* choose the eigenvalue of [rho beta1; beta1 alpha2] closest to rho */
186
          LAPACKlaev2_(&rho,&beta1,&alpha2,&rt1,&rt2,&cs1,&sn1);
187
          if (PetscAbsScalar(rt1-rho) < PetscAbsScalar(rt2-rho)) rho = rt1;
188
          else rho = rt2;
189
#endif
190
        }
833 dsic.upv.es!antodo 191
        /* update operator according to new shift */
1247 slepc 192
        PetscPushErrorHandler(PetscIgnoreErrorHandler,PETSC_NULL);
833 dsic.upv.es!antodo 193
        ierr = STSetShift(eps->OP,rho);
194
        PetscPopErrorHandler();
195
        if (ierr) {
196
          eps->eigr[eps->nconv] = rho;
197
          relerr = PETSC_MACHINE_EPSILON;
198
          rho = sigma;
199
          ierr = STSetShift(eps->OP,rho);CHKERRQ(ierr);
200
        }      
819 dsic.upv.es!jroman 201
      }
202
    }
203
 
204
    eps->errest[eps->nconv] = relerr;
205
    EPSMonitor(eps,eps->its,eps->nconv,eps->eigr,eps->eigi,eps->errest,eps->nconv+1);
206
 
207
    /* purge previously converged eigenvectors */
1761 antodo 208
    if (select) {
819 dsic.upv.es!jroman 209
      for (i=0;i<eps->nconv;i++) {
1755 antodo 210
        if(PetscAbsScalar(rho-eps->eigr[i])>eps->its*anorm/1000) select[i] = PETSC_TRUE;
211
        else select[i] = PETSC_FALSE;
819 dsic.upv.es!jroman 212
      }
1755 antodo 213
      ierr = IPOrthogonalize(eps->ip,eps->nds,eps->DS,eps->nconv,select,eps->V,y,PETSC_NULL,&norm,PETSC_NULL);CHKERRQ(ierr);
819 dsic.upv.es!jroman 214
    } else {
1755 antodo 215
      ierr = IPOrthogonalize(eps->ip,eps->nds,eps->DS,eps->nconv,PETSC_NULL,eps->V,y,PETSC_NULL,&norm,PETSC_NULL);CHKERRQ(ierr);
819 dsic.upv.es!jroman 216
    }
217
 
428 dsic.upv.es!jroman 218
    /* v = y/||y||_B */
219
    ierr = VecCopy(y,v);CHKERRQ(ierr);
828 dsic.upv.es!antodo 220
    ierr = VecScale(v,1.0/norm);CHKERRQ(ierr);
6 dsic.upv.es!jroman 221
 
819 dsic.upv.es!jroman 222
    /* if relerr<tol, accept eigenpair */
223
    if (relerr<eps->tol) {
224
      eps->nconv = eps->nconv + 1;
1136 slepc 225
      if (eps->nconv==eps->nev) eps->reason = EPS_CONVERGED_TOL;
226
      else {
227
        v = eps->V[eps->nconv];
228
        ierr = EPSGetStartVector(eps,eps->nconv,v,&breakdown);CHKERRQ(ierr);
229
        if (breakdown) {
230
          eps->reason = EPS_DIVERGED_BREAKDOWN;
231
          PetscInfo(eps,"Unable to generate more start vectors\n");
232
        }
1057 slepc 233
      }
819 dsic.upv.es!jroman 234
    }
235
 
1057 slepc 236
    if (eps->its >= eps->max_it) eps->reason = EPS_DIVERGED_ITS;
819 dsic.upv.es!jroman 237
  }
238
 
1761 antodo 239
  ierr = PetscFree(select);CHKERRQ(ierr);
819 dsic.upv.es!jroman 240
 
241
  PetscFunctionReturn(0);
242
}
243
 
244
#undef __FUNCT__  
245
#define __FUNCT__ "EPSSolve_TS_POWER"
246
PetscErrorCode EPSSolve_TS_POWER(EPS eps)
247
{
248
  PetscErrorCode ierr;
249
  EPS_POWER      *power = (EPS_POWER *)eps->data;
250
  Vec            v, w, y, z, e;
251
  Mat            A;
252
  PetscReal      relerr, norm, rt1, rt2, cs1;
838 dsic.upv.es!jroman 253
  PetscScalar    theta, alpha, beta, rho, delta, sigma, alpha2, beta1, sn1;
819 dsic.upv.es!jroman 254
 
255
  PetscFunctionBegin;
256
  v = eps->V[0];
1590 slepc 257
  y = eps->work[1];
819 dsic.upv.es!jroman 258
  e = eps->work[0];
259
  w = eps->W[0];
1607 slepc 260
  z = eps->work[2];
819 dsic.upv.es!jroman 261
 
1057 slepc 262
  ierr = EPSGetStartVector(eps,0,v,PETSC_NULL);CHKERRQ(ierr);
1937 jroman 263
  ierr = EPSGetStartVectorLeft(eps,0,w,PETSC_NULL);CHKERRQ(ierr);
819 dsic.upv.es!jroman 264
  ierr = STGetShift(eps->OP,&sigma);CHKERRQ(ierr);    /* original shift */
833 dsic.upv.es!antodo 265
  rho = sigma;
819 dsic.upv.es!jroman 266
 
267
  while (eps->its<eps->max_it) {
1220 slepc 268
    eps->its++;
269
 
819 dsic.upv.es!jroman 270
    /* y = OP v, z = OP' w */
428 dsic.upv.es!jroman 271
    ierr = STApply(eps->OP,v,y);CHKERRQ(ierr);
819 dsic.upv.es!jroman 272
    ierr = STApplyTranspose(eps->OP,w,z);CHKERRQ(ierr);
6 dsic.upv.es!jroman 273
 
819 dsic.upv.es!jroman 274
    /* theta = (v,z)_B */
1345 slepc 275
    ierr = IPInnerProduct(eps->ip,v,z,&theta);CHKERRQ(ierr);
6 dsic.upv.es!jroman 276
 
1940 jroman 277
    if (power->shift_type == EPS_POWER_SHIFT_CONSTANT) { /* direct & inverse iteration */
819 dsic.upv.es!jroman 278
 
279
      /* approximate eigenvalue is the Rayleigh quotient */
280
      eps->eigr[eps->nconv] = theta;
281
 
282
      /* compute relative errors (right and left) */
283
      ierr = VecCopy(y,e);CHKERRQ(ierr);
828 dsic.upv.es!antodo 284
      ierr = VecAXPY(e,-theta,v);CHKERRQ(ierr);
819 dsic.upv.es!jroman 285
      ierr = VecNorm(e,NORM_2,&norm);CHKERRQ(ierr);
286
      relerr = norm / PetscAbsScalar(theta);
287
      eps->errest[eps->nconv] = relerr;
288
      ierr = VecCopy(z,e);CHKERRQ(ierr);
828 dsic.upv.es!antodo 289
      ierr = VecAXPY(e,-theta,w);CHKERRQ(ierr);
819 dsic.upv.es!jroman 290
      ierr = VecNorm(e,NORM_2,&norm);CHKERRQ(ierr);
291
      relerr = norm / PetscAbsScalar(theta);
292
      eps->errest_left[eps->nconv] = relerr;
293
 
294
    } else {  /* RQI */
295
 
296
      /* delta = sqrt(y,z)_B */
1345 slepc 297
      ierr = IPInnerProduct(eps->ip,y,z,&alpha);CHKERRQ(ierr);
819 dsic.upv.es!jroman 298
      if (alpha==0.0) SETERRQ(1,"Breakdown in two-sided Power/RQI");
299
      delta = PetscSqrtScalar(alpha);
300
 
301
      /* compute relative error */
833 dsic.upv.es!antodo 302
      if (rho == 0.0) relerr = PETSC_MAX;
840 dsic.upv.es!antodo 303
      else relerr = 1.0 / (PetscAbsScalar(delta*rho));
819 dsic.upv.es!jroman 304
      eps->errest[eps->nconv] = relerr;
305
      eps->errest_left[eps->nconv] = relerr;
306
 
307
      /* approximate eigenvalue is the shift */
308
      eps->eigr[eps->nconv] = rho;
309
 
310
      /* compute new shift */
833 dsic.upv.es!antodo 311
      if (eps->errest[eps->nconv]<eps->tol && eps->errest_left[eps->nconv]<eps->tol) {
819 dsic.upv.es!jroman 312
        rho = sigma; /* if converged, restore original shift */
833 dsic.upv.es!antodo 313
        ierr = STSetShift(eps->OP,rho);CHKERRQ(ierr);
314
      } else {
819 dsic.upv.es!jroman 315
        rho = rho + theta/(delta*delta);  /* Rayleigh quotient R(v,w) */
1940 jroman 316
        if (power->shift_type == EPS_POWER_SHIFT_WILKINSON) {
1063 slepc 317
#if defined(SLEPC_MISSING_LAPACK_LAEV2)
819 dsic.upv.es!jroman 318
          SETERRQ(PETSC_ERR_SUP,"LAEV2 - Lapack routine is unavailable.");
319
#else
320
          /* beta1 is the norm of the residual associated to R(v,w) */
828 dsic.upv.es!antodo 321
          ierr = VecAXPY(v,-theta/(delta*delta),y);CHKERRQ(ierr);
322
          ierr = VecScale(v,1.0/delta);CHKERRQ(ierr);
1345 slepc 323
          ierr = IPNorm(eps->ip,v,&norm);CHKERRQ(ierr);
819 dsic.upv.es!jroman 324
          beta1 = norm;
325
 
326
          /* alpha2 = (e'*A*e)/(beta1*beta1), where e is the residual */
327
          ierr = STGetOperators(eps->OP,&A,PETSC_NULL);CHKERRQ(ierr);
328
          ierr = MatMult(A,v,e);CHKERRQ(ierr);
329
          ierr = VecDot(v,e,&alpha2);CHKERRQ(ierr);
330
          alpha2 = alpha2 / (beta1 * beta1);
331
 
332
          /* choose the eigenvalue of [rho beta1; beta1 alpha2] closest to rho */
333
          LAPACKlaev2_(&rho,&beta1,&alpha2,&rt1,&rt2,&cs1,&sn1);
334
          if (PetscAbsScalar(rt1-rho) < PetscAbsScalar(rt2-rho)) rho = rt1;
335
          else rho = rt2;
336
#endif
450 dsic.upv.es!antodo 337
        }
833 dsic.upv.es!antodo 338
        /* update operator according to new shift */
1247 slepc 339
        PetscPushErrorHandler(PetscIgnoreErrorHandler,PETSC_NULL);
833 dsic.upv.es!antodo 340
        ierr = STSetShift(eps->OP,rho);
341
        PetscPopErrorHandler();
342
        if (ierr) {
343
          eps->eigr[eps->nconv] = rho;
344
          eps->errest[eps->nconv] = PETSC_MACHINE_EPSILON;
345
          eps->errest_left[eps->nconv] = PETSC_MACHINE_EPSILON;
346
          rho = sigma;
347
          ierr = STSetShift(eps->OP,rho);CHKERRQ(ierr);
348
        }
819 dsic.upv.es!jroman 349
      }
350
    }
351
 
352
    EPSMonitor(eps,eps->its,eps->nconv,eps->eigr,eps->eigi,eps->errest,eps->nconv+1);
953 dsic.upv.es!jroman 353
    EPSMonitor(eps,eps->its,eps->nconv,eps->eigr,eps->eigi,eps->errest_left,eps->nconv+1);
819 dsic.upv.es!jroman 354
 
355
    /* purge previously converged eigenvectors */
1345 slepc 356
    ierr = IPBiOrthogonalize(eps->ip,eps->nconv,eps->V,eps->W,z,PETSC_NULL,PETSC_NULL);CHKERRQ(ierr);
357
    ierr = IPBiOrthogonalize(eps->ip,eps->nconv,eps->W,eps->V,y,PETSC_NULL,PETSC_NULL);CHKERRQ(ierr);
819 dsic.upv.es!jroman 358
 
359
    /* normalize so that (y,z)_B=1  */
360
    ierr = VecCopy(y,v);CHKERRQ(ierr);
361
    ierr = VecCopy(z,w);CHKERRQ(ierr);
1345 slepc 362
    ierr = IPInnerProduct(eps->ip,y,z,&alpha);CHKERRQ(ierr);
819 dsic.upv.es!jroman 363
    if (alpha==0.0) SETERRQ(1,"Breakdown in two-sided Power/RQI");
838 dsic.upv.es!jroman 364
    delta = PetscSqrtScalar(PetscAbsScalar(alpha));
365
    beta = 1.0/PetscConj(alpha/delta);
366
    delta = 1.0/delta;
367
    ierr = VecScale(w,beta);CHKERRQ(ierr);
368
    ierr = VecScale(v,delta);CHKERRQ(ierr);
444 dsic.upv.es!antodo 369
 
819 dsic.upv.es!jroman 370
    /* if relerr<tol (both right and left), accept eigenpair */
371
    if (eps->errest[eps->nconv]<eps->tol && eps->errest_left[eps->nconv]<eps->tol) {
6 dsic.upv.es!jroman 372
      eps->nconv = eps->nconv + 1;
373
      if (eps->nconv==eps->nev) break;
374
      v = eps->V[eps->nconv];
1057 slepc 375
      ierr = EPSGetStartVector(eps,eps->nconv,v,PETSC_NULL);CHKERRQ(ierr);
819 dsic.upv.es!jroman 376
      w = eps->W[eps->nconv];
1937 jroman 377
      ierr = EPSGetStartVectorLeft(eps,eps->nconv,w,PETSC_NULL);CHKERRQ(ierr);
6 dsic.upv.es!jroman 378
    }
379
  }
380
 
381
  if( eps->nconv == eps->nev ) eps->reason = EPS_CONVERGED_TOL;
382
  else eps->reason = EPS_DIVERGED_ITS;
383
 
384
  PetscFunctionReturn(0);
385
}
386
 
444 dsic.upv.es!antodo 387
#undef __FUNCT__  
388
#define __FUNCT__ "EPSBackTransform_POWER"
476 dsic.upv.es!antodo 389
PetscErrorCode EPSBackTransform_POWER(EPS eps)
444 dsic.upv.es!antodo 390
{
476 dsic.upv.es!antodo 391
  PetscErrorCode ierr;
444 dsic.upv.es!antodo 392
  EPS_POWER *power = (EPS_POWER *)eps->data;
393
 
394
  PetscFunctionBegin;
1940 jroman 395
  if (power->shift_type == EPS_POWER_SHIFT_CONSTANT) {
444 dsic.upv.es!antodo 396
    ierr = EPSBackTransform_Default(eps);CHKERRQ(ierr);
397
  }
398
  PetscFunctionReturn(0);
399
}
400
 
401
#undef __FUNCT__  
402
#define __FUNCT__ "EPSSetFromOptions_POWER"
476 dsic.upv.es!antodo 403
PetscErrorCode EPSSetFromOptions_POWER(EPS eps)
444 dsic.upv.es!antodo 404
{
476 dsic.upv.es!antodo 405
  PetscErrorCode ierr;
406
  EPS_POWER      *power = (EPS_POWER *)eps->data;
407
  PetscTruth     flg;
982 slepc 408
  PetscInt       i;
476 dsic.upv.es!antodo 409
  const char     *shift_list[3] = { "constant", "rayleigh", "wilkinson" };
444 dsic.upv.es!antodo 410
 
411
  PetscFunctionBegin;
2102 eromero 412
  ierr = PetscOptionsBegin(((PetscObject)eps)->comm,((PetscObject)eps)->prefix,"POWER Options","EPS");CHKERRQ(ierr);
982 slepc 413
  ierr = PetscOptionsEList("-eps_power_shift_type","Shift type","EPSPowerSetShiftType",shift_list,3,shift_list[power->shift_type],&i,&flg);CHKERRQ(ierr);
1002 slepc 414
  if (flg ) power->shift_type = (EPSPowerShiftType)i;
1940 jroman 415
  if (power->shift_type != EPS_POWER_SHIFT_CONSTANT) {
2092 jroman 416
    ierr = STSetType(eps->OP,STSINVERT);CHKERRQ(ierr);
444 dsic.upv.es!antodo 417
  }
2102 eromero 418
  ierr = PetscOptionsEnd();CHKERRQ(ierr);
444 dsic.upv.es!antodo 419
  PetscFunctionReturn(0);
420
}
421
 
6 dsic.upv.es!jroman 422
EXTERN_C_BEGIN
423
#undef __FUNCT__  
444 dsic.upv.es!antodo 424
#define __FUNCT__ "EPSPowerSetShiftType_POWER"
476 dsic.upv.es!antodo 425
PetscErrorCode EPSPowerSetShiftType_POWER(EPS eps,EPSPowerShiftType shift)
444 dsic.upv.es!antodo 426
{
476 dsic.upv.es!antodo 427
  EPS_POWER *power = (EPS_POWER *)eps->data;
444 dsic.upv.es!antodo 428
 
429
  PetscFunctionBegin;
430
  switch (shift) {
1940 jroman 431
    case EPS_POWER_SHIFT_CONSTANT:
432
    case EPS_POWER_SHIFT_RAYLEIGH:
433
    case EPS_POWER_SHIFT_WILKINSON:
444 dsic.upv.es!antodo 434
      power->shift_type = shift;
435
      break;
436
    default:
437
      SETERRQ(PETSC_ERR_ARG_OUTOFRANGE,"Invalid shift type");
438
  }
439
  PetscFunctionReturn(0);
440
}
441
EXTERN_C_END
442
 
443
#undef __FUNCT__  
444
#define __FUNCT__ "EPSPowerSetShiftType"
446 dsic.upv.es!jroman 445
/*@
446
   EPSPowerSetShiftType - Sets the type of shifts used during the power
447
   iteration. This can be used to emulate the Rayleigh Quotient Iteration
448
   (RQI) method.
449
 
450
   Collective on EPS
451
 
452
   Input Parameters:
453
+  eps - the eigenproblem solver context
454
-  shift - the type of shift
455
 
456
   Options Database Key:
457
.  -eps_power_shift_type - Sets the shift type (either 'constant' or
458
                           'rayleigh' or 'wilkinson')
459
 
460
   Notes:
1940 jroman 461
   By default, shifts are constant (EPS_POWER_SHIFT_CONSTANT) and the iteration
446 dsic.upv.es!jroman 462
   is the simple power method (or inverse iteration if a shift-and-invert
463
   transformation is being used).
464
 
1940 jroman 465
   A variable shift can be specified (EPS_POWER_SHIFT_RAYLEIGH or
466
   EPS_POWER_SHIFT_WILKINSON). In this case, the iteration behaves rather like
446 dsic.upv.es!jroman 467
   a cubic converging method as RQI. See the users manual for details.
468
 
469
   Level: advanced
470
 
1364 slepc 471
.seealso: EPSPowerGetShiftType(), STSetShift(), EPSPowerShiftType
446 dsic.upv.es!jroman 472
@*/
476 dsic.upv.es!antodo 473
PetscErrorCode EPSPowerSetShiftType(EPS eps,EPSPowerShiftType shift)
444 dsic.upv.es!antodo 474
{
476 dsic.upv.es!antodo 475
  PetscErrorCode ierr, (*f)(EPS,EPSPowerShiftType);
444 dsic.upv.es!antodo 476
 
477
  PetscFunctionBegin;
478
  PetscValidHeaderSpecific(eps,EPS_COOKIE,1);
479
  ierr = PetscObjectQueryFunction((PetscObject)eps,"EPSPowerSetShiftType_C",(void (**)())&f);CHKERRQ(ierr);
480
  if (f) {
481
    ierr = (*f)(eps,shift);CHKERRQ(ierr);
482
  }
483
  PetscFunctionReturn(0);
484
}
485
 
486
EXTERN_C_BEGIN
487
#undef __FUNCT__  
488
#define __FUNCT__ "EPSPowerGetShiftType_POWER"
476 dsic.upv.es!antodo 489
PetscErrorCode EPSPowerGetShiftType_POWER(EPS eps,EPSPowerShiftType *shift)
444 dsic.upv.es!antodo 490
{
491
  EPS_POWER  *power = (EPS_POWER *)eps->data;
492
  PetscFunctionBegin;
493
  *shift = power->shift_type;
494
  PetscFunctionReturn(0);
495
}
496
EXTERN_C_END
497
 
498
#undef __FUNCT__  
499
#define __FUNCT__ "EPSPowerGetShiftType"
707 dsic.upv.es!antodo 500
/*@C
446 dsic.upv.es!jroman 501
   EPSPowerGetShiftType - Gets the type of shifts used during the power
502
   iteration.
503
 
504
   Collective on EPS
505
 
506
   Input Parameter:
507
.  eps - the eigenproblem solver context
508
 
509
   Input Parameter:
510
.  shift - the type of shift
511
 
512
   Level: advanced
513
 
1364 slepc 514
.seealso: EPSPowerSetShiftType(), EPSPowerShiftType
446 dsic.upv.es!jroman 515
@*/
476 dsic.upv.es!antodo 516
PetscErrorCode EPSPowerGetShiftType(EPS eps,EPSPowerShiftType *shift)
444 dsic.upv.es!antodo 517
{
476 dsic.upv.es!antodo 518
  PetscErrorCode ierr, (*f)(EPS,EPSPowerShiftType*);
444 dsic.upv.es!antodo 519
 
520
  PetscFunctionBegin;
521
  PetscValidHeaderSpecific(eps,EPS_COOKIE,1);
522
  ierr = PetscObjectQueryFunction((PetscObject)eps,"EPSPowerGetShiftType_C",(void (**)())&f);CHKERRQ(ierr);
523
  if (f) {
524
    ierr = (*f)(eps,shift);CHKERRQ(ierr);
525
  }
526
  PetscFunctionReturn(0);
527
}
528
 
450 dsic.upv.es!antodo 529
#undef __FUNCT__  
1925 jroman 530
#define __FUNCT__ "EPSDestroy_POWER"
531
PetscErrorCode EPSDestroy_POWER(EPS eps)
532
{
533
  PetscErrorCode ierr;
534
 
535
  PetscFunctionBegin;
536
  PetscValidHeaderSpecific(eps,EPS_COOKIE,1);
537
  ierr = EPSDestroy_Default(eps);CHKERRQ(ierr);
538
  ierr = PetscObjectComposeFunctionDynamic((PetscObject)eps,"EPSPowerSetShiftType_C","",PETSC_NULL);CHKERRQ(ierr);
539
  ierr = PetscObjectComposeFunctionDynamic((PetscObject)eps,"EPSPowerGetShiftType_C","",PETSC_NULL);CHKERRQ(ierr);
540
  PetscFunctionReturn(0);
541
}
542
 
543
#undef __FUNCT__  
450 dsic.upv.es!antodo 544
#define __FUNCT__ "EPSView_POWER"
476 dsic.upv.es!antodo 545
PetscErrorCode EPSView_POWER(EPS eps,PetscViewer viewer)
450 dsic.upv.es!antodo 546
{
476 dsic.upv.es!antodo 547
  PetscErrorCode ierr;
548
  EPS_POWER      *power = (EPS_POWER *)eps->data;
549
  PetscTruth     isascii;
550
  const char     *shift_list[3] = { "constant", "rayleigh", "wilkinson" };
450 dsic.upv.es!antodo 551
 
552
  PetscFunctionBegin;
553
  ierr = PetscTypeCompare((PetscObject)viewer,PETSC_VIEWER_ASCII,&isascii);CHKERRQ(ierr);
554
  if (!isascii) {
1940 jroman 555
    SETERRQ1(1,"Viewer type %s not supported for EPS_POWER",((PetscObject)viewer)->type_name);
450 dsic.upv.es!antodo 556
  }  
557
  ierr = PetscViewerASCIIPrintf(viewer,"shift type: %s\n",shift_list[power->shift_type]);CHKERRQ(ierr);
558
  PetscFunctionReturn(0);
559
}
560
 
444 dsic.upv.es!antodo 561
EXTERN_C_BEGIN
562
#undef __FUNCT__  
6 dsic.upv.es!jroman 563
#define __FUNCT__ "EPSCreate_POWER"
476 dsic.upv.es!antodo 564
PetscErrorCode EPSCreate_POWER(EPS eps)
6 dsic.upv.es!jroman 565
{
476 dsic.upv.es!antodo 566
  PetscErrorCode ierr;
567
  EPS_POWER      *power;
444 dsic.upv.es!antodo 568
 
6 dsic.upv.es!jroman 569
  PetscFunctionBegin;
444 dsic.upv.es!antodo 570
  ierr = PetscNew(EPS_POWER,&power);CHKERRQ(ierr);
571
  PetscLogObjectMemory(eps,sizeof(EPS_POWER));
572
  eps->data                      = (void *) power;
503 dsic.upv.es!antodo 573
  eps->ops->setup                = EPSSetUp_POWER;
444 dsic.upv.es!antodo 574
  eps->ops->setfromoptions       = EPSSetFromOptions_POWER;
1925 jroman 575
  eps->ops->destroy              = EPSDestroy_POWER;
450 dsic.upv.es!antodo 576
  eps->ops->view                 = EPSView_POWER;
444 dsic.upv.es!antodo 577
  eps->ops->backtransform        = EPSBackTransform_POWER;
503 dsic.upv.es!antodo 578
  eps->ops->computevectors       = EPSComputeVectors_Default;
1940 jroman 579
  power->shift_type              = EPS_POWER_SHIFT_CONSTANT;
444 dsic.upv.es!antodo 580
  ierr = PetscObjectComposeFunctionDynamic((PetscObject)eps,"EPSPowerSetShiftType_C","EPSPowerSetShiftType_POWER",EPSPowerSetShiftType_POWER);CHKERRQ(ierr);
581
  ierr = PetscObjectComposeFunctionDynamic((PetscObject)eps,"EPSPowerGetShiftType_C","EPSPowerGetShiftType_POWER",EPSPowerGetShiftType_POWER);CHKERRQ(ierr);
6 dsic.upv.es!jroman 582
  PetscFunctionReturn(0);
583
}
584
EXTERN_C_END
531 dsic.upv.es!jroman 585