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