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