Subversion Repositories slepc-dev

Rev

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