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
2575 eromero 25
   Copyright (c) 2002-2011, Universitat 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
 
2729 jroman 43
#include <slepc-private/epsimpl.h>                /*I "slepceps.h" I*/
2283 jroman 44
#include <slepcblaslapack.h>
6 dsic.upv.es!jroman 45
 
2324 jroman 46
PetscErrorCode EPSSolve_Power(EPS);
47
PetscErrorCode EPSSolve_TS_Power(EPS);
1947 jroman 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__  
2324 jroman 54
#define __FUNCT__ "EPSSetUp_Power"
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;
2216 jroman 59
  PetscBool      flg;
476 dsic.upv.es!antodo 60
  STMatMode      mode;
6 dsic.upv.es!jroman 61
 
62
  PetscFunctionBegin;
63
  if (eps->ncv) {
2214 jroman 64
    if (eps->ncv<eps->nev) SETERRQ(((PetscObject)eps)->comm,1,"The value of ncv must be at least nev");
6 dsic.upv.es!jroman 65
  }
66
  else eps->ncv = eps->nev;
2499 jroman 67
  if (eps->mpd) { ierr = PetscInfo(eps,"Warning: parameter mpd ignored\n");CHKERRQ(ierr); }
1928 jroman 68
  if (!eps->max_it) eps->max_it = PetscMax(2000,100*eps->n);
2613 jroman 69
  if (!eps->which) { ierr = EPSDefaultSetWhich(eps);CHKERRQ(ierr); }
70
  if (eps->which!=EPS_LARGEST_MAGNITUDE && eps->which !=EPS_TARGET_MAGNITUDE)
2214 jroman 71
    SETERRQ(((PetscObject)eps)->comm,1,"Wrong value of eps->which");
1940 jroman 72
  if (power->shift_type != EPS_POWER_SHIFT_CONSTANT) {
2613 jroman 73
    ierr = PetscTypeCompareAny((PetscObject)eps->OP,&flg,STSINVERT,STCAYLEY,"");CHKERRQ(ierr);
819 dsic.upv.es!jroman 74
    if (!flg)
2613 jroman 75
      SETERRQ(((PetscObject)eps)->comm,PETSC_ERR_SUP,"Variable shifts only allowed in shift-and-invert or Cayley ST");
444 dsic.upv.es!antodo 76
    ierr = STGetMatMode(eps->OP,&mode);CHKERRQ(ierr);
1940 jroman 77
    if (mode == ST_MATMODE_INPLACE)
2214 jroman 78
      SETERRQ(((PetscObject)eps)->comm,PETSC_ERR_SUP,"ST matrix mode inplace does not work with variable shifts");
444 dsic.upv.es!antodo 79
  }
2499 jroman 80
  if (eps->extraction) { ierr = PetscInfo(eps,"Warning: extraction type ignored\n");CHKERRQ(ierr); }
1940 jroman 81
  if (eps->balance!=EPS_BALANCE_NONE)
2214 jroman 82
    SETERRQ(((PetscObject)eps)->comm,PETSC_ERR_SUP,"Balancing not supported in this solver");
259 dsic.upv.es!antodo 83
  ierr = EPSAllocateSolution(eps);CHKERRQ(ierr);
1947 jroman 84
  if (eps->leftvecs) {
1937 jroman 85
    ierr = EPSDefaultGetWork(eps,3);CHKERRQ(ierr);
86
  } else {
87
    ierr = EPSDefaultGetWork(eps,2);CHKERRQ(ierr);
88
  }
1947 jroman 89
 
90
  /* dispatch solve method */
2324 jroman 91
  if (eps->leftvecs) eps->ops->solve = EPSSolve_TS_Power;
92
  else eps->ops->solve = EPSSolve_Power;
6 dsic.upv.es!jroman 93
  PetscFunctionReturn(0);
94
}
95
 
96
#undef __FUNCT__  
2324 jroman 97
#define __FUNCT__ "EPSSolve_Power"
98
PetscErrorCode EPSSolve_Power(EPS eps)
6 dsic.upv.es!jroman 99
{
2739 jroman 100
#if defined(SLEPC_MISSING_LAPACK_LAEV2)
101
  PetscFunctionBegin;
102
  SETERRQ(PETSC_COMM_SELF,PETSC_ERR_SUP,"LAEV2 - Lapack routine is unavailable.");
103
#else
476 dsic.upv.es!antodo 104
  PetscErrorCode ierr;
105
  EPS_POWER      *power = (EPS_POWER *)eps->data;
1755 antodo 106
  PetscInt       i;
2331 jroman 107
  Vec            v,y,e;
819 dsic.upv.es!jroman 108
  Mat            A;
2331 jroman 109
  PetscReal      relerr,norm,rt1,rt2,cs1,anorm;
110
  PetscScalar    theta,rho,delta,sigma,alpha2,beta1,sn1;
2216 jroman 111
  PetscBool      breakdown,*select = PETSC_NULL,hasnorm;
6 dsic.upv.es!jroman 112
 
113
  PetscFunctionBegin;
114
  v = eps->V[0];
1755 antodo 115
  y = eps->work[1];
428 dsic.upv.es!jroman 116
  e = eps->work[0];
6 dsic.upv.es!jroman 117
 
819 dsic.upv.es!jroman 118
  /* prepare for selective orthogonalization of converged vectors */
1940 jroman 119
  if (power->shift_type != EPS_POWER_SHIFT_CONSTANT && eps->nev>1) {
1761 antodo 120
    ierr = STGetOperators(eps->OP,&A,PETSC_NULL);CHKERRQ(ierr);
121
    ierr = MatHasOperation(A,MATOP_NORM,&hasnorm);CHKERRQ(ierr);
122
    if (hasnorm) {
819 dsic.upv.es!jroman 123
      ierr = MatNorm(A,NORM_INFINITY,&anorm);CHKERRQ(ierr);
2216 jroman 124
      ierr = PetscMalloc(eps->nev*sizeof(PetscBool),&select);CHKERRQ(ierr);
819 dsic.upv.es!jroman 125
    }
126
  }
6 dsic.upv.es!jroman 127
 
1057 slepc 128
  ierr = EPSGetStartVector(eps,0,v,PETSC_NULL);CHKERRQ(ierr);
819 dsic.upv.es!jroman 129
  ierr = STGetShift(eps->OP,&sigma);CHKERRQ(ierr);    /* original shift */
833 dsic.upv.es!antodo 130
  rho = sigma;
819 dsic.upv.es!jroman 131
 
1057 slepc 132
  while (eps->reason == EPS_CONVERGED_ITERATING) {
1220 slepc 133
    eps->its = eps->its + 1;
252 dsic.upv.es!jroman 134
 
819 dsic.upv.es!jroman 135
    /* y = OP v */
136
    ierr = STApply(eps->OP,v,y);CHKERRQ(ierr);
450 dsic.upv.es!antodo 137
 
819 dsic.upv.es!jroman 138
    /* theta = (v,y)_B */
1345 slepc 139
    ierr = IPInnerProduct(eps->ip,v,y,&theta);CHKERRQ(ierr);
819 dsic.upv.es!jroman 140
 
1940 jroman 141
    if (power->shift_type == EPS_POWER_SHIFT_CONSTANT) { /* direct & inverse iteration */
819 dsic.upv.es!jroman 142
 
143
      /* approximate eigenvalue is the Rayleigh quotient */
144
      eps->eigr[eps->nconv] = theta;
145
 
146
      /* compute relative error as ||y-theta v||_2/|theta| */
147
      ierr = VecCopy(y,e);CHKERRQ(ierr);
828 dsic.upv.es!antodo 148
      ierr = VecAXPY(e,-theta,v);CHKERRQ(ierr);
819 dsic.upv.es!jroman 149
      ierr = VecNorm(e,NORM_2,&norm);CHKERRQ(ierr);
150
      relerr = norm / PetscAbsScalar(theta);
151
 
152
    } else {  /* RQI */
153
 
154
      /* delta = ||y||_B */
1345 slepc 155
      ierr = IPNorm(eps->ip,y,&norm);CHKERRQ(ierr);
819 dsic.upv.es!jroman 156
      delta = norm;
157
 
158
      /* compute relative error */
2280 jroman 159
      if (rho == 0.0) relerr = PETSC_MAX_REAL;
833 dsic.upv.es!antodo 160
      else relerr = 1.0 / (norm*PetscAbsScalar(rho));
819 dsic.upv.es!jroman 161
 
162
      /* approximate eigenvalue is the shift */
163
      eps->eigr[eps->nconv] = rho;
164
 
165
      /* compute new shift */
833 dsic.upv.es!antodo 166
      if (relerr<eps->tol) {
167
        rho = sigma; /* if converged, restore original shift */
168
        ierr = STSetShift(eps->OP,rho);CHKERRQ(ierr);
169
      } else {
819 dsic.upv.es!jroman 170
        rho = rho + theta/(delta*delta);  /* Rayleigh quotient R(v) */
1940 jroman 171
        if (power->shift_type == EPS_POWER_SHIFT_WILKINSON) {
819 dsic.upv.es!jroman 172
          /* beta1 is the norm of the residual associated to R(v) */
828 dsic.upv.es!antodo 173
          ierr = VecAXPY(v,-theta/(delta*delta),y);CHKERRQ(ierr);
174
          ierr = VecScale(v,1.0/delta);CHKERRQ(ierr);
1345 slepc 175
          ierr = IPNorm(eps->ip,v,&norm);CHKERRQ(ierr);
819 dsic.upv.es!jroman 176
          beta1 = norm;
177
 
178
          /* alpha2 = (e'*A*e)/(beta1*beta1), where e is the residual */
179
          ierr = STGetOperators(eps->OP,&A,PETSC_NULL);CHKERRQ(ierr);
180
          ierr = MatMult(A,v,e);CHKERRQ(ierr);
181
          ierr = VecDot(v,e,&alpha2);CHKERRQ(ierr);
182
          alpha2 = alpha2 / (beta1 * beta1);
183
 
184
          /* choose the eigenvalue of [rho beta1; beta1 alpha2] closest to rho */
2740 jroman 185
          ierr = PetscFPTrapPush(PETSC_FP_TRAP_OFF);CHKERRQ(ierr);
819 dsic.upv.es!jroman 186
          LAPACKlaev2_(&rho,&beta1,&alpha2,&rt1,&rt2,&cs1,&sn1);
2740 jroman 187
          ierr = PetscFPTrapPop();CHKERRQ(ierr);
819 dsic.upv.es!jroman 188
          if (PetscAbsScalar(rt1-rho) < PetscAbsScalar(rt2-rho)) rho = rt1;
189
          else rho = rt2;
190
        }
2316 jroman 191
        /* update operator according to new shift */
192
        PetscPushErrorHandler(PetscIgnoreErrorHandler,PETSC_NULL);
193
        ierr = STSetShift(eps->OP,rho);
194
        PetscPopErrorHandler();
195
        if (ierr) {
833 dsic.upv.es!antodo 196
          eps->eigr[eps->nconv] = rho;
2316 jroman 197
          relerr = PETSC_MACHINE_EPSILON;
198
          rho = sigma;
833 dsic.upv.es!antodo 199
          ierr = STSetShift(eps->OP,rho);CHKERRQ(ierr);
2316 jroman 200
        }
819 dsic.upv.es!jroman 201
      }
202
    }
203
 
204
    eps->errest[eps->nconv] = relerr;
2313 jroman 205
    ierr = EPSMonitor(eps,eps->its,eps->nconv,eps->eigr,eps->eigi,eps->errest,eps->nconv+1);CHKERRQ(ierr);
819 dsic.upv.es!jroman 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 {
2316 jroman 227
        v = eps->V[eps->nconv];
228
        ierr = EPSGetStartVector(eps,eps->nconv,v,&breakdown);CHKERRQ(ierr);
229
        if (breakdown) {
1136 slepc 230
          eps->reason = EPS_DIVERGED_BREAKDOWN;
2499 jroman 231
          ierr = PetscInfo(eps,"Unable to generate more start vectors\n");CHKERRQ(ierr);
2316 jroman 232
        }
1057 slepc 233
      }
819 dsic.upv.es!jroman 234
    }
1057 slepc 235
    if (eps->its >= eps->max_it) eps->reason = EPS_DIVERGED_ITS;
819 dsic.upv.es!jroman 236
  }
1761 antodo 237
  ierr = PetscFree(select);CHKERRQ(ierr);
819 dsic.upv.es!jroman 238
  PetscFunctionReturn(0);
2739 jroman 239
#endif
819 dsic.upv.es!jroman 240
}
241
 
242
#undef __FUNCT__  
2324 jroman 243
#define __FUNCT__ "EPSSolve_TS_Power"
244
PetscErrorCode EPSSolve_TS_Power(EPS eps)
819 dsic.upv.es!jroman 245
{
2739 jroman 246
#if defined(SLEPC_MISSING_LAPACK_LAEV2)
247
  PetscFunctionBegin;
248
  SETERRQ(PETSC_COMM_SELF,PETSC_ERR_SUP,"LAEV2 - Lapack routine is unavailable.");
249
#else
819 dsic.upv.es!jroman 250
  PetscErrorCode ierr;
251
  EPS_POWER      *power = (EPS_POWER *)eps->data;
2331 jroman 252
  Vec            v,w,y,z,e;
819 dsic.upv.es!jroman 253
  Mat            A;
2331 jroman 254
  PetscReal      relerr,norm,rt1,rt2,cs1;
255
  PetscScalar    theta,alpha,beta,rho,delta,sigma,alpha2,beta1,sn1;
819 dsic.upv.es!jroman 256
 
257
  PetscFunctionBegin;
258
  v = eps->V[0];
1590 slepc 259
  y = eps->work[1];
819 dsic.upv.es!jroman 260
  e = eps->work[0];
261
  w = eps->W[0];
1607 slepc 262
  z = eps->work[2];
819 dsic.upv.es!jroman 263
 
1057 slepc 264
  ierr = EPSGetStartVector(eps,0,v,PETSC_NULL);CHKERRQ(ierr);
1937 jroman 265
  ierr = EPSGetStartVectorLeft(eps,0,w,PETSC_NULL);CHKERRQ(ierr);
819 dsic.upv.es!jroman 266
  ierr = STGetShift(eps->OP,&sigma);CHKERRQ(ierr);    /* original shift */
833 dsic.upv.es!antodo 267
  rho = sigma;
819 dsic.upv.es!jroman 268
 
269
  while (eps->its<eps->max_it) {
1220 slepc 270
    eps->its++;
271
 
819 dsic.upv.es!jroman 272
    /* y = OP v, z = OP' w */
428 dsic.upv.es!jroman 273
    ierr = STApply(eps->OP,v,y);CHKERRQ(ierr);
819 dsic.upv.es!jroman 274
    ierr = STApplyTranspose(eps->OP,w,z);CHKERRQ(ierr);
6 dsic.upv.es!jroman 275
 
819 dsic.upv.es!jroman 276
    /* theta = (v,z)_B */
1345 slepc 277
    ierr = IPInnerProduct(eps->ip,v,z,&theta);CHKERRQ(ierr);
6 dsic.upv.es!jroman 278
 
1940 jroman 279
    if (power->shift_type == EPS_POWER_SHIFT_CONSTANT) { /* direct & inverse iteration */
819 dsic.upv.es!jroman 280
 
281
      /* approximate eigenvalue is the Rayleigh quotient */
282
      eps->eigr[eps->nconv] = theta;
283
 
284
      /* compute relative errors (right and left) */
285
      ierr = VecCopy(y,e);CHKERRQ(ierr);
828 dsic.upv.es!antodo 286
      ierr = VecAXPY(e,-theta,v);CHKERRQ(ierr);
819 dsic.upv.es!jroman 287
      ierr = VecNorm(e,NORM_2,&norm);CHKERRQ(ierr);
288
      relerr = norm / PetscAbsScalar(theta);
289
      eps->errest[eps->nconv] = relerr;
290
      ierr = VecCopy(z,e);CHKERRQ(ierr);
828 dsic.upv.es!antodo 291
      ierr = VecAXPY(e,-theta,w);CHKERRQ(ierr);
819 dsic.upv.es!jroman 292
      ierr = VecNorm(e,NORM_2,&norm);CHKERRQ(ierr);
293
      relerr = norm / PetscAbsScalar(theta);
294
      eps->errest_left[eps->nconv] = relerr;
295
 
296
    } else {  /* RQI */
297
 
298
      /* delta = sqrt(y,z)_B */
1345 slepc 299
      ierr = IPInnerProduct(eps->ip,y,z,&alpha);CHKERRQ(ierr);
2214 jroman 300
      if (alpha==0.0) SETERRQ(((PetscObject)eps)->comm,1,"Breakdown in two-sided Power/RQI");
819 dsic.upv.es!jroman 301
      delta = PetscSqrtScalar(alpha);
302
 
303
      /* compute relative error */
2280 jroman 304
      if (rho == 0.0) relerr = PETSC_MAX_REAL;
840 dsic.upv.es!antodo 305
      else relerr = 1.0 / (PetscAbsScalar(delta*rho));
819 dsic.upv.es!jroman 306
      eps->errest[eps->nconv] = relerr;
307
      eps->errest_left[eps->nconv] = relerr;
308
 
309
      /* approximate eigenvalue is the shift */
310
      eps->eigr[eps->nconv] = rho;
311
 
312
      /* compute new shift */
833 dsic.upv.es!antodo 313
      if (eps->errest[eps->nconv]<eps->tol && eps->errest_left[eps->nconv]<eps->tol) {
819 dsic.upv.es!jroman 314
        rho = sigma; /* if converged, restore original shift */
833 dsic.upv.es!antodo 315
        ierr = STSetShift(eps->OP,rho);CHKERRQ(ierr);
316
      } else {
819 dsic.upv.es!jroman 317
        rho = rho + theta/(delta*delta);  /* Rayleigh quotient R(v,w) */
1940 jroman 318
        if (power->shift_type == EPS_POWER_SHIFT_WILKINSON) {
819 dsic.upv.es!jroman 319
          /* beta1 is the norm of the residual associated to R(v,w) */
828 dsic.upv.es!antodo 320
          ierr = VecAXPY(v,-theta/(delta*delta),y);CHKERRQ(ierr);
321
          ierr = VecScale(v,1.0/delta);CHKERRQ(ierr);
1345 slepc 322
          ierr = IPNorm(eps->ip,v,&norm);CHKERRQ(ierr);
819 dsic.upv.es!jroman 323
          beta1 = norm;
324
 
325
          /* alpha2 = (e'*A*e)/(beta1*beta1), where e is the residual */
326
          ierr = STGetOperators(eps->OP,&A,PETSC_NULL);CHKERRQ(ierr);
327
          ierr = MatMult(A,v,e);CHKERRQ(ierr);
328
          ierr = VecDot(v,e,&alpha2);CHKERRQ(ierr);
329
          alpha2 = alpha2 / (beta1 * beta1);
330
 
331
          /* choose the eigenvalue of [rho beta1; beta1 alpha2] closest to rho */
2740 jroman 332
          ierr = PetscFPTrapPush(PETSC_FP_TRAP_OFF);CHKERRQ(ierr);
819 dsic.upv.es!jroman 333
          LAPACKlaev2_(&rho,&beta1,&alpha2,&rt1,&rt2,&cs1,&sn1);
2740 jroman 334
          ierr = PetscFPTrapPop();CHKERRQ(ierr);
819 dsic.upv.es!jroman 335
          if (PetscAbsScalar(rt1-rho) < PetscAbsScalar(rt2-rho)) rho = rt1;
336
          else rho = rt2;
450 dsic.upv.es!antodo 337
        }
2316 jroman 338
        /* update operator according to new shift */
339
        PetscPushErrorHandler(PetscIgnoreErrorHandler,PETSC_NULL);
340
        ierr = STSetShift(eps->OP,rho);
341
        PetscPopErrorHandler();
342
        if (ierr) {
833 dsic.upv.es!antodo 343
          eps->eigr[eps->nconv] = rho;
2316 jroman 344
          eps->errest[eps->nconv] = PETSC_MACHINE_EPSILON;
345
          eps->errest_left[eps->nconv] = PETSC_MACHINE_EPSILON;
346
          rho = sigma;
833 dsic.upv.es!antodo 347
          ierr = STSetShift(eps->OP,rho);CHKERRQ(ierr);
2316 jroman 348
        }
819 dsic.upv.es!jroman 349
      }
350
    }
351
 
2313 jroman 352
    ierr = EPSMonitor(eps,eps->its,eps->nconv,eps->eigr,eps->eigi,eps->errest,eps->nconv+1);CHKERRQ(ierr);
353
    ierr = EPSMonitor(eps,eps->its,eps->nconv,eps->eigr,eps->eigi,eps->errest_left,eps->nconv+1);CHKERRQ(ierr);
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);
2214 jroman 363
    if (alpha==0.0) SETERRQ(((PetscObject)eps)->comm,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
  }
2331 jroman 380
  if (eps->nconv == eps->nev) eps->reason = EPS_CONVERGED_TOL;
6 dsic.upv.es!jroman 381
  else eps->reason = EPS_DIVERGED_ITS;
382
  PetscFunctionReturn(0);
2739 jroman 383
#endif
6 dsic.upv.es!jroman 384
}
385
 
444 dsic.upv.es!antodo 386
#undef __FUNCT__  
2324 jroman 387
#define __FUNCT__ "EPSBackTransform_Power"
388
PetscErrorCode EPSBackTransform_Power(EPS eps)
444 dsic.upv.es!antodo 389
{
476 dsic.upv.es!antodo 390
  PetscErrorCode ierr;
2317 jroman 391
  EPS_POWER      *power = (EPS_POWER *)eps->data;
444 dsic.upv.es!antodo 392
 
393
  PetscFunctionBegin;
1940 jroman 394
  if (power->shift_type == EPS_POWER_SHIFT_CONSTANT) {
444 dsic.upv.es!antodo 395
    ierr = EPSBackTransform_Default(eps);CHKERRQ(ierr);
396
  }
397
  PetscFunctionReturn(0);
398
}
399
 
400
#undef __FUNCT__  
2324 jroman 401
#define __FUNCT__ "EPSSetFromOptions_Power"
402
PetscErrorCode EPSSetFromOptions_Power(EPS eps)
444 dsic.upv.es!antodo 403
{
2321 jroman 404
  PetscErrorCode    ierr;
405
  EPS_POWER         *power = (EPS_POWER *)eps->data;
406
  PetscBool         flg;
407
  EPSPowerShiftType shift;
444 dsic.upv.es!antodo 408
 
409
  PetscFunctionBegin;
2384 jroman 410
  ierr = PetscOptionsHead("EPS Power Options");CHKERRQ(ierr);
2321 jroman 411
  ierr = PetscOptionsEnum("-eps_power_shift_type","Shift type","EPSPowerSetShiftType",EPSPowerShiftTypes,(PetscEnum)power->shift_type,(PetscEnum*)&shift,&flg);CHKERRQ(ierr);
412
  if (flg) { ierr = EPSPowerSetShiftType(eps,shift);CHKERRQ(ierr); }
1940 jroman 413
  if (power->shift_type != EPS_POWER_SHIFT_CONSTANT) {
2092 jroman 414
    ierr = STSetType(eps->OP,STSINVERT);CHKERRQ(ierr);
444 dsic.upv.es!antodo 415
  }
2384 jroman 416
  ierr = PetscOptionsTail();CHKERRQ(ierr);
444 dsic.upv.es!antodo 417
  PetscFunctionReturn(0);
418
}
419
 
6 dsic.upv.es!jroman 420
EXTERN_C_BEGIN
421
#undef __FUNCT__  
2324 jroman 422
#define __FUNCT__ "EPSPowerSetShiftType_Power"
423
PetscErrorCode EPSPowerSetShiftType_Power(EPS eps,EPSPowerShiftType shift)
444 dsic.upv.es!antodo 424
{
476 dsic.upv.es!antodo 425
  EPS_POWER *power = (EPS_POWER *)eps->data;
444 dsic.upv.es!antodo 426
 
427
  PetscFunctionBegin;
428
  switch (shift) {
1940 jroman 429
    case EPS_POWER_SHIFT_CONSTANT:
430
    case EPS_POWER_SHIFT_RAYLEIGH:
431
    case EPS_POWER_SHIFT_WILKINSON:
444 dsic.upv.es!antodo 432
      power->shift_type = shift;
433
      break;
434
    default:
2214 jroman 435
      SETERRQ(((PetscObject)eps)->comm,PETSC_ERR_ARG_OUTOFRANGE,"Invalid shift type");
444 dsic.upv.es!antodo 436
  }
437
  PetscFunctionReturn(0);
438
}
439
EXTERN_C_END
440
 
441
#undef __FUNCT__  
442
#define __FUNCT__ "EPSPowerSetShiftType"
446 dsic.upv.es!jroman 443
/*@
444
   EPSPowerSetShiftType - Sets the type of shifts used during the power
445
   iteration. This can be used to emulate the Rayleigh Quotient Iteration
446
   (RQI) method.
447
 
2328 jroman 448
   Logically Collective on EPS
446 dsic.upv.es!jroman 449
 
450
   Input Parameters:
451
+  eps - the eigenproblem solver context
452
-  shift - the type of shift
453
 
454
   Options Database Key:
455
.  -eps_power_shift_type - Sets the shift type (either 'constant' or
456
                           'rayleigh' or 'wilkinson')
457
 
458
   Notes:
1940 jroman 459
   By default, shifts are constant (EPS_POWER_SHIFT_CONSTANT) and the iteration
446 dsic.upv.es!jroman 460
   is the simple power method (or inverse iteration if a shift-and-invert
461
   transformation is being used).
462
 
1940 jroman 463
   A variable shift can be specified (EPS_POWER_SHIFT_RAYLEIGH or
464
   EPS_POWER_SHIFT_WILKINSON). In this case, the iteration behaves rather like
446 dsic.upv.es!jroman 465
   a cubic converging method as RQI. See the users manual for details.
466
 
467
   Level: advanced
468
 
1364 slepc 469
.seealso: EPSPowerGetShiftType(), STSetShift(), EPSPowerShiftType
446 dsic.upv.es!jroman 470
@*/
476 dsic.upv.es!antodo 471
PetscErrorCode EPSPowerSetShiftType(EPS eps,EPSPowerShiftType shift)
444 dsic.upv.es!antodo 472
{
2221 jroman 473
  PetscErrorCode ierr;
444 dsic.upv.es!antodo 474
 
475
  PetscFunctionBegin;
2213 jroman 476
  PetscValidHeaderSpecific(eps,EPS_CLASSID,1);
2326 jroman 477
  PetscValidLogicalCollectiveEnum(eps,shift,2);
2221 jroman 478
  ierr = PetscTryMethod(eps,"EPSPowerSetShiftType_C",(EPS,EPSPowerShiftType),(eps,shift));CHKERRQ(ierr);
444 dsic.upv.es!antodo 479
  PetscFunctionReturn(0);
480
}
481
 
482
EXTERN_C_BEGIN
483
#undef __FUNCT__  
2324 jroman 484
#define __FUNCT__ "EPSPowerGetShiftType_Power"
485
PetscErrorCode EPSPowerGetShiftType_Power(EPS eps,EPSPowerShiftType *shift)
444 dsic.upv.es!antodo 486
{
487
  EPS_POWER  *power = (EPS_POWER *)eps->data;
2317 jroman 488
 
444 dsic.upv.es!antodo 489
  PetscFunctionBegin;
490
  *shift = power->shift_type;
491
  PetscFunctionReturn(0);
492
}
493
EXTERN_C_END
494
 
495
#undef __FUNCT__  
496
#define __FUNCT__ "EPSPowerGetShiftType"
707 dsic.upv.es!antodo 497
/*@C
446 dsic.upv.es!jroman 498
   EPSPowerGetShiftType - Gets the type of shifts used during the power
499
   iteration.
500
 
2328 jroman 501
   Not Collective
446 dsic.upv.es!jroman 502
 
503
   Input Parameter:
504
.  eps - the eigenproblem solver context
505
 
506
   Input Parameter:
507
.  shift - the type of shift
508
 
509
   Level: advanced
510
 
1364 slepc 511
.seealso: EPSPowerSetShiftType(), EPSPowerShiftType
446 dsic.upv.es!jroman 512
@*/
476 dsic.upv.es!antodo 513
PetscErrorCode EPSPowerGetShiftType(EPS eps,EPSPowerShiftType *shift)
444 dsic.upv.es!antodo 514
{
2221 jroman 515
  PetscErrorCode ierr;
444 dsic.upv.es!antodo 516
 
517
  PetscFunctionBegin;
2213 jroman 518
  PetscValidHeaderSpecific(eps,EPS_CLASSID,1);
2326 jroman 519
  PetscValidPointer(shift,2);
2221 jroman 520
  ierr = PetscTryMethod(eps,"EPSPowerGetShiftType_C",(EPS,EPSPowerShiftType*),(eps,shift));CHKERRQ(ierr);
444 dsic.upv.es!antodo 521
  PetscFunctionReturn(0);
522
}
523
 
450 dsic.upv.es!antodo 524
#undef __FUNCT__  
2324 jroman 525
#define __FUNCT__ "EPSDestroy_Power"
526
PetscErrorCode EPSDestroy_Power(EPS eps)
1925 jroman 527
{
528
  PetscErrorCode ierr;
529
 
530
  PetscFunctionBegin;
2348 jroman 531
  ierr = PetscFree(eps->data);CHKERRQ(ierr);
1925 jroman 532
  ierr = PetscObjectComposeFunctionDynamic((PetscObject)eps,"EPSPowerSetShiftType_C","",PETSC_NULL);CHKERRQ(ierr);
533
  ierr = PetscObjectComposeFunctionDynamic((PetscObject)eps,"EPSPowerGetShiftType_C","",PETSC_NULL);CHKERRQ(ierr);
534
  PetscFunctionReturn(0);
535
}
536
 
537
#undef __FUNCT__  
2324 jroman 538
#define __FUNCT__ "EPSView_Power"
539
PetscErrorCode EPSView_Power(EPS eps,PetscViewer viewer)
450 dsic.upv.es!antodo 540
{
476 dsic.upv.es!antodo 541
  PetscErrorCode ierr;
542
  EPS_POWER      *power = (EPS_POWER *)eps->data;
2216 jroman 543
  PetscBool      isascii;
450 dsic.upv.es!antodo 544
 
545
  PetscFunctionBegin;
2215 jroman 546
  ierr = PetscTypeCompare((PetscObject)viewer,PETSCVIEWERASCII,&isascii);CHKERRQ(ierr);
450 dsic.upv.es!antodo 547
  if (!isascii) {
2324 jroman 548
    SETERRQ1(((PetscObject)eps)->comm,1,"Viewer type %s not supported for EPS Power",((PetscObject)viewer)->type_name);
450 dsic.upv.es!antodo 549
  }  
2365 jroman 550
  ierr = PetscViewerASCIIPrintf(viewer,"  Power: %s shifts\n",EPSPowerShiftTypes[power->shift_type]);CHKERRQ(ierr);
450 dsic.upv.es!antodo 551
  PetscFunctionReturn(0);
552
}
553
 
444 dsic.upv.es!antodo 554
EXTERN_C_BEGIN
555
#undef __FUNCT__  
2324 jroman 556
#define __FUNCT__ "EPSCreate_Power"
557
PetscErrorCode EPSCreate_Power(EPS eps)
6 dsic.upv.es!jroman 558
{
476 dsic.upv.es!antodo 559
  PetscErrorCode ierr;
444 dsic.upv.es!antodo 560
 
6 dsic.upv.es!jroman 561
  PetscFunctionBegin;
2329 jroman 562
  ierr = PetscNewLog(eps,EPS_POWER,&eps->data);CHKERRQ(ierr);
2324 jroman 563
  eps->ops->setup                = EPSSetUp_Power;
564
  eps->ops->setfromoptions       = EPSSetFromOptions_Power;
565
  eps->ops->destroy              = EPSDestroy_Power;
2348 jroman 566
  eps->ops->reset                = EPSReset_Default;
2324 jroman 567
  eps->ops->view                 = EPSView_Power;
568
  eps->ops->backtransform        = EPSBackTransform_Power;
503 dsic.upv.es!antodo 569
  eps->ops->computevectors       = EPSComputeVectors_Default;
2324 jroman 570
  ierr = PetscObjectComposeFunctionDynamic((PetscObject)eps,"EPSPowerSetShiftType_C","EPSPowerSetShiftType_Power",EPSPowerSetShiftType_Power);CHKERRQ(ierr);
571
  ierr = PetscObjectComposeFunctionDynamic((PetscObject)eps,"EPSPowerGetShiftType_C","EPSPowerGetShiftType_Power",EPSPowerGetShiftType_Power);CHKERRQ(ierr);
6 dsic.upv.es!jroman 572
  PetscFunctionReturn(0);
573
}
574
EXTERN_C_END
531 dsic.upv.es!jroman 575