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
1217 slepc 1
/*                      
2
 
3
   SLEPc eigensolver: "krylovschur"
4
 
5
   Method: Krylov-Schur
6
 
7
   Algorithm:
8
 
9
       Single-vector Krylov-Schur method for both symmetric and non-symmetric
10
       problems.
11
 
12
   References:
13
 
14
       [1] "Krylov-Schur Methods in SLEPc", SLEPc Technical Report STR-7,
15
           available at http://www.grycap.upv.es/slepc.
16
 
17
       [2] G.W. Stewart, "A Krylov-Schur Algorithm for Large Eigenproblems",
18
           SIAM J. Matrix Analysis and App., 23(3), pp. 601-614, 2001.
19
 
20
   Last update: Oct 2006
21
 
1376 slepc 22
   - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
23
      SLEPc - Scalable Library for Eigenvalue Problem Computations
24
      Copyright (c) 2002-2007, Universidad Politecnica de Valencia, Spain
25
 
26
      This file is part of SLEPc. See the README file for conditions of use
27
      and additional information.
28
   - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
1217 slepc 29
*/
1376 slepc 30
 
1171 slepc 31
#include "src/eps/epsimpl.h"                /*I "slepceps.h" I*/
32
#include "slepcblaslapack.h"
33
 
34
#undef __FUNCT__  
35
#define __FUNCT__ "EPSSetUp_KRYLOVSCHUR"
36
PetscErrorCode EPSSetUp_KRYLOVSCHUR(EPS eps)
37
{
38
  PetscErrorCode ierr;
39
  PetscInt       N;
40
 
41
  PetscFunctionBegin;
1385 slepc 42
  ierr = VecGetSize(eps->vec_initial,&N);CHKERRQ(ierr);
1171 slepc 43
  if (eps->ncv) {
1172 slepc 44
    if (eps->ncv<eps->nev+1) SETERRQ(1,"The value of ncv must be at least nev+1");
1171 slepc 45
  }
46
  else eps->ncv = PetscMin(N,PetscMax(2*eps->nev,eps->nev+15));
1220 slepc 47
  if (!eps->max_it) eps->max_it = PetscMax(100,2*N/eps->ncv);
1177 slepc 48
  if (eps->ishermitian && (eps->which==EPS_LARGEST_IMAGINARY || eps->which==EPS_SMALLEST_IMAGINARY))
49
    SETERRQ(1,"Wrong value of eps->which");
1220 slepc 50
 
1426 slepc 51
  if (!eps->projection) {
52
    ierr = EPSSetProjection(eps,EPS_RITZ);CHKERRQ(ierr);
53
  } else if (eps->projection!=EPS_RITZ && eps->projection!=EPS_HARMONIC) {
54
    SETERRQ(PETSC_ERR_SUP,"Unsupported projection type\n");
55
  }
56
 
1171 slepc 57
  ierr = EPSAllocateSolution(eps);CHKERRQ(ierr);
58
  ierr = PetscFree(eps->T);CHKERRQ(ierr);
59
  ierr = PetscMalloc(eps->ncv*eps->ncv*sizeof(PetscScalar),&eps->T);CHKERRQ(ierr);
1345 slepc 60
  ierr = EPSDefaultGetWork(eps,2);CHKERRQ(ierr);
1171 slepc 61
  PetscFunctionReturn(0);
62
}
63
 
64
#undef __FUNCT__  
1428 slepc 65
#define __FUNCT__ "EPSTranslateHarmonic"
66
/*
67
   EPSTranslateHarmonic - Computes a translation of the Krylov decomposition
68
   in order to perform a harmonic projection.
69
 
70
   On input:
71
     A Krylov decomposition
72
 
73
                    OP * U = U * S + u * b^T
74
 
75
     S is the projected matrix (leading dimension is m)
76
     [U, u] is the basis of the Krylov subspace
77
     b is assumed to be beta*e_m^T
78
 
79
   Workspace:
80
     B is workspace to store a working copy of S and a working vector (last column)
81
     ipiv is workspace for pivots (int of length m)
82
 
83
   On output:
84
     S is updated as S + g*b', with g = (B-sigma*eye(m))'\b
85
     u is updated as u - U*g
86
     u is renormalized so beta is updated accordingly
87
*/
88
PetscErrorCode EPSTranslateHarmonic(EPS eps,PetscScalar *S,int m,PetscScalar *B,Vec *U,Vec u,PetscReal *beta,int *ipiv)
89
{
90
#if defined(PETSC_MISSING_LAPACK_GETRF) || defined(PETSC_MISSING_LAPACK_GETRS)
91
  PetscFunctionBegin;
92
  SETERRQ(PETSC_ERR_SUP,"GETRF,GETRS - Lapack routines are unavailable.");
93
#else
94
  PetscErrorCode ierr;
95
  PetscBLASInt   info,one = 1;
96
  PetscReal      gamma;
97
  int            i;
98
 
99
  PetscFunctionBegin;
100
  /* Copy S to workspace B */
101
  ierr = PetscMemcpy(B,S,m*m*sizeof(PetscScalar));CHKERRQ(ierr);
102
  /* Last columns of B stores vectors b and g */
103
  ierr = PetscMemzero(B+m*m,m*sizeof(PetscScalar));CHKERRQ(ierr);
104
  B[(m-1)+m*m] = (PetscScalar)(*beta);
105
 
106
  /* g = (B-sigma*eye(m))'\b */
107
  for (i=0;i<m;i++)
108
    B[i+i*m] -= eps->target;
109
  LAPACKgetrf_(&m,&m,B,&m,ipiv,&info);
110
  if (info<0) SETERRQ(PETSC_ERR_LIB,"Bad argument to LU factorization");
111
  if (info>0) SETERRQ(PETSC_ERR_MAT_LU_ZRPVT,"Bad LU factorization");
112
  ierr = PetscLogFlops(2*m*m*m/3);CHKERRQ(ierr);
113
  LAPACKgetrs_("C",&m,&one,B,&m,ipiv,B+m*m,&m,&info);
114
  if (info) SETERRQ(PETSC_ERR_LIB,"GETRS - Bad solve");
115
  ierr = PetscLogFlops(2*m*m-m);CHKERRQ(ierr);
116
 
117
  /* S = S + g*b' */
118
  for (i=0;i<m;i++)
119
    S[i+(m-1)*m] = S[i+(m-1)*m] + B[i+m*m]*(*beta);
120
 
121
  /* u = u - U*g */
122
  for (i=0;i<m;i++)
123
    B[i+m*m] = -B[i+m*m];
124
  ierr = VecMAXPY(u,m,B+m*m,U);CHKERRQ(ierr);        
125
 
126
  /* Renormalize u */
127
  ierr = IPNorm(eps->ip,u,&gamma);CHKERRQ(ierr);
128
  ierr = VecScale(u,1.0/gamma);CHKERRQ(ierr);
129
  *beta = (*beta)*gamma;
130
 
131
  PetscFunctionReturn(0);
132
#endif
133
}
134
 
135
#undef __FUNCT__  
1424 slepc 136
#define __FUNCT__ "EPSProjectedKSSymm"
137
/*
138
   EPSProjectedKSSym - Solves the projected eigenproblem in the Krylov-Schur
139
   method (symmetric case).
140
 
141
   On input:
142
     l is the number of vectors kept in previous restart (0 means first restart)
143
     S is the projected matrix (leading dimension is lds)
144
     Q is an orthogonal transformation matrix if l=0 (leading dimension is n)
145
 
146
   Workspace:
147
     ritz temporarily stores computed Ritz values
148
     perm is used for representing the permutation used for sorting values
149
 
150
   On output:
151
     S has (real) Schur form with diagonal blocks sorted appropriately
152
     Q contains the accumulated orthogonal transformations used in the process
153
*/
154
PetscErrorCode EPSProjectedKSSym(EPS eps,int l,PetscScalar *S,int lds,PetscScalar *Q,int n,PetscReal *ritz,int *perm)
155
{
156
  PetscErrorCode ierr;
157
  int            i,j;
158
 
159
  PetscFunctionBegin;
160
  /* Reduce S to diagonal form, S <- Q S Q' */
161
  if (l==0) {
162
    ierr = EPSDenseTridiagonal(n,S+eps->nconv*(lds+1),lds,ritz,Q+eps->nconv*n);CHKERRQ(ierr);
163
  } else {
164
    ierr = EPSDenseHEP(n,S+eps->nconv*(lds+1),lds,ritz,Q+eps->nconv*n);CHKERRQ(ierr);
165
  }
166
  /* Sort the remaining columns of the Schur form */
167
  if (eps->which == EPS_SMALLEST_REAL) {
168
    for (i=0;i<n;i++)
169
      eps->eigr[i+eps->nconv] = ritz[i];
170
  } else {
171
#ifdef PETSC_USE_COMPLEX
172
    for (i=0;i<n;i++)
173
      eps->eigr[i+eps->nconv] = ritz[i];
174
    ierr = EPSSortEigenvalues(n,eps->eigr+eps->nconv,eps->eigi,eps->which,n,perm);CHKERRQ(ierr);
175
#else
176
    ierr = EPSSortEigenvalues(n,ritz,eps->eigi+eps->nconv,eps->which,n,perm);CHKERRQ(ierr);
177
#endif
178
    for (i=0;i<n;i++)
179
      eps->eigr[i+eps->nconv] = ritz[perm[i]];
180
    ierr = PetscMemcpy(S,Q+eps->nconv*n,n*n*sizeof(PetscScalar));CHKERRQ(ierr);
181
    for (j=0;j<n;j++)
182
      for (i=0;i<n;i++)
183
        Q[(j+eps->nconv)*n+i] = S[perm[j]*n+i];
184
  }
185
  /* rebuild S from eigr */
186
  for (i=eps->nconv;i<eps->nv;i++) {
187
    S[i*(eps->ncv+1)] = eps->eigr[i];
188
    for (j=i+1;j<eps->ncv;j++)
189
      S[i*eps->ncv+j] = 0.0;
190
  }
191
  PetscFunctionReturn(0);
192
}
193
 
194
#undef __FUNCT__  
195
#define __FUNCT__ "EPSProjectedKSNonsymm"
196
/*
197
   EPSProjectedKSNonsym - Solves the projected eigenproblem in the Krylov-Schur
198
   method (non-symmetric case).
199
 
200
   On input:
201
     l is the number of vectors kept in previous restart (0 means first restart)
202
     S is the projected matrix (leading dimension is lds)
203
     Q is an orthogonal transformation matrix if l=0 (leading dimension is n)
204
 
205
   On output:
206
     S has (real) Schur form with diagonal blocks sorted appropriately
207
     Q contains the accumulated orthogonal transformations used in the process
208
*/
209
PetscErrorCode EPSProjectedKSNonsym(EPS eps,int l,PetscScalar *S,int lds,PetscScalar *Q,int n)
210
{
211
  PetscErrorCode ierr;
212
  int            i;
213
 
214
  PetscFunctionBegin;
215
  if (l==0) {
216
    ierr = PetscMemzero(Q,n*n*sizeof(PetscScalar));CHKERRQ(ierr);
217
    for (i=0;i<n;i++)
218
      Q[i*(n+1)] = 1.0;
219
  } else {
220
    /* Reduce S to Hessenberg form, S <- Q S Q' */
221
    ierr = EPSDenseHessenberg(n,eps->nconv,S,lds,Q);CHKERRQ(ierr);
222
  }
223
  /* Reduce S to (quasi-)triangular form, S <- Q S Q' */
224
  ierr = EPSDenseSchur(n,eps->nconv,S,lds,Q,eps->eigr,eps->eigi);CHKERRQ(ierr);
225
  /* Sort the remaining columns of the Schur form */
1428 slepc 226
  if (eps->projection==EPS_HARMONIC) {
227
    ierr = EPSSortDenseSchurTarget(n,eps->nconv,S,lds,Q,eps->eigr,eps->eigi,eps->target);CHKERRQ(ierr);    
228
  } else {
229
    ierr = EPSSortDenseSchur(n,eps->nconv,S,lds,Q,eps->eigr,eps->eigi,eps->which);CHKERRQ(ierr);    
230
  }
1424 slepc 231
  PetscFunctionReturn(0);
232
}
233
 
234
#undef __FUNCT__  
1171 slepc 235
#define __FUNCT__ "EPSSolve_KRYLOVSCHUR"
236
PetscErrorCode EPSSolve_KRYLOVSCHUR(EPS eps)
237
{
238
  PetscErrorCode ierr;
1428 slepc 239
  int            i,j,k,l,n,lwork,*perm;
1345 slepc 240
  Vec            u=eps->work[1];
1428 slepc 241
  PetscScalar    *S=eps->T,*B,*Q,*work;
1177 slepc 242
  PetscReal      beta,*ritz;
1171 slepc 243
  PetscTruth     breakdown;
244
 
245
  PetscFunctionBegin;
246
  ierr = PetscMemzero(S,eps->ncv*eps->ncv*sizeof(PetscScalar));CHKERRQ(ierr);
1428 slepc 247
  ierr = PetscMalloc(eps->ncv*(eps->ncv+1)*sizeof(PetscScalar),&B);CHKERRQ(ierr);
1171 slepc 248
  ierr = PetscMalloc(eps->ncv*eps->ncv*sizeof(PetscScalar),&Q);CHKERRQ(ierr);
249
  lwork = (eps->ncv+4)*eps->ncv;
1175 slepc 250
  if (!eps->ishermitian) {
251
    ierr = PetscMalloc(lwork*sizeof(PetscScalar),&work);CHKERRQ(ierr);
252
  } else {
1177 slepc 253
    ierr = PetscMalloc(eps->ncv*sizeof(PetscReal),&ritz);CHKERRQ(ierr);
1175 slepc 254
  }
1428 slepc 255
  ierr = PetscMalloc(eps->ncv*sizeof(int),&perm);CHKERRQ(ierr);
1171 slepc 256
 
257
  /* Get the starting Arnoldi vector */
258
  ierr = EPSGetStartVector(eps,0,eps->V[0],PETSC_NULL);CHKERRQ(ierr);
1172 slepc 259
  l = 0;
1171 slepc 260
 
261
  /* Restart loop */
262
  while (eps->reason == EPS_CONVERGED_ITERATING) {
1220 slepc 263
    eps->its++;
1171 slepc 264
 
265
    /* Compute an nv-step Arnoldi factorization */
266
    eps->nv = eps->ncv;
1172 slepc 267
    ierr = EPSBasicArnoldi(eps,PETSC_FALSE,S,eps->V,eps->nconv+l,&eps->nv,u,&beta,&breakdown);CHKERRQ(ierr);
1171 slepc 268
    ierr = VecScale(u,1.0/beta);CHKERRQ(ierr);
269
 
1428 slepc 270
    /* Compute translation of Krylov decomposition if harmonic projection used */
271
    if (eps->projection==EPS_HARMONIC) {
272
      ierr = EPSTranslateHarmonic(eps,S,eps->ncv,B,eps->V,u,&beta,perm);CHKERRQ(ierr);
273
    }
274
 
1424 slepc 275
    /* Solve projected problem and compute residual norm estimates */
276
    if (eps->ishermitian) {
277
      n = eps->nv-eps->nconv;
278
      ierr = EPSProjectedKSSym(eps,l,S,eps->ncv,Q,n,ritz,perm);CHKERRQ(ierr);
1175 slepc 279
      for (i=eps->nconv;i<eps->nv;i++)
280
        eps->errest[i] = beta*PetscAbsScalar(Q[(i+1)*n-1]) / PetscAbsScalar(eps->eigr[i]);
1424 slepc 281
    } else { /* non-hermitian */
282
      n = eps->nv;
283
      ierr = EPSProjectedKSNonsym(eps,l,S,eps->ncv,Q,n);CHKERRQ(ierr);
284
      ierr = ArnoldiResiduals(S,eps->ncv,Q,beta,eps->nconv,n,eps->eigr,eps->eigi,eps->errest,work);CHKERRQ(ierr);
1172 slepc 285
    }
1171 slepc 286
 
1172 slepc 287
    /* Check convergence */
288
    k = eps->nconv;
1175 slepc 289
    while (k<eps->nv && eps->errest[k]<eps->tol) k++;    
1172 slepc 290
    if (eps->its >= eps->max_it) eps->reason = EPS_DIVERGED_ITS;
291
    if (k >= eps->nev) eps->reason = EPS_CONVERGED_TOL;
292
 
1175 slepc 293
    /* Update l */
1172 slepc 294
    if (eps->reason != EPS_CONVERGED_ITERATING || breakdown) l = 0;
295
    else {
296
      l = (eps->nv-k)/2;
297
#if !defined(PETSC_USE_COMPLEX)
1185 slepc 298
      if (S[(k+l-1)*(eps->ncv+1)+1] != 0.0) {
1172 slepc 299
        if (k+l<eps->nv-1) l = l+1;
300
        else l = l-1;
301
      }
302
#endif
303
    }
1175 slepc 304
 
305
    /* Update the corresponding vectors V(:,idx) = V*Q(:,idx) */
1172 slepc 306
    for (i=eps->nconv;i<k+l;i++) {
1171 slepc 307
      ierr = VecSet(eps->AV[i],0.0);CHKERRQ(ierr);
1175 slepc 308
      if (!eps->ishermitian) {
309
        ierr = VecMAXPY(eps->AV[i],n,Q+i*n,eps->V);CHKERRQ(ierr);        
310
      } else {
311
        ierr = VecMAXPY(eps->AV[i],n,Q+i*n,eps->V+eps->nconv);CHKERRQ(ierr);
312
      }
1171 slepc 313
    }
1172 slepc 314
    for (i=eps->nconv;i<k+l;i++) {
1171 slepc 315
      ierr = VecCopy(eps->AV[i],eps->V[i]);CHKERRQ(ierr);
316
    }
317
    eps->nconv = k;
318
 
319
    EPSMonitor(eps,eps->its,eps->nconv,eps->eigr,eps->eigi,eps->errest,eps->nv);
1172 slepc 320
 
321
    if (eps->reason == EPS_CONVERGED_ITERATING) {
1171 slepc 322
      if (breakdown) {
1172 slepc 323
        /* start a new Arnoldi factorization */
324
        PetscInfo2(eps,"Breakdown in Krylov-Schur method (it=%i norm=%g)\n",eps->its,beta);
325
        ierr = EPSGetStartVector(eps,k,eps->V[k],&breakdown);CHKERRQ(ierr);
326
        if (breakdown) {
327
          eps->reason = EPS_DIVERGED_BREAKDOWN;
328
          PetscInfo(eps,"Unable to generate more start vectors\n");
329
        }
330
      } else {
331
        /* update the Arnoldi-Schur decomposition */
332
        for (i=k;i<k+l;i++) {
1175 slepc 333
          S[i*eps->ncv+k+l] = Q[(i+1)*n-1]*beta;
1172 slepc 334
        }
1428 slepc 335
        if (eps->projection==EPS_HARMONIC) {
336
          /* force orthogonality of u */
337
          ierr = IPOrthogonalize(eps->ip,l,PETSC_NULL,eps->V,u,B+eps->ncv*eps->ncv,&beta,PETSC_NULL,eps->work[0]);CHKERRQ(ierr);
338
          /* S = S + g*b' */
339
          for (i=0;i<l;i++) {
340
            for (j=k;j<k+l;j++) {
341
              S[i+j*eps->ncv] += B[i+eps->ncv*eps->ncv]*S[k+l+j*eps->ncv];
342
            }
343
          }
344
          ierr = VecScale(u,1.0/beta);CHKERRQ(ierr);
345
          for (i=k;i<k+l;i++) {
346
            S[i*eps->ncv+k+l] *= beta;
347
          }
348
        }
349
        ierr = VecCopy(u,eps->V[k+l]);CHKERRQ(ierr);
1171 slepc 350
      }
1175 slepc 351
    }
1172 slepc 352
  }
1171 slepc 353
 
1428 slepc 354
  ierr = PetscFree(B);CHKERRQ(ierr);
1171 slepc 355
  ierr = PetscFree(Q);CHKERRQ(ierr);
1175 slepc 356
  if (!eps->ishermitian) {
357
    ierr = PetscFree(work);CHKERRQ(ierr);
358
  } else {
1177 slepc 359
    ierr = PetscFree(ritz);CHKERRQ(ierr);
1175 slepc 360
  }
1428 slepc 361
  ierr = PetscFree(perm);CHKERRQ(ierr);
1171 slepc 362
  PetscFunctionReturn(0);
363
}
364
 
365
EXTERN_C_BEGIN
366
#undef __FUNCT__  
367
#define __FUNCT__ "EPSCreate_KRYLOVSCHUR"
368
PetscErrorCode EPSCreate_KRYLOVSCHUR(EPS eps)
369
{
370
  PetscFunctionBegin;
371
  eps->data                      = PETSC_NULL;
372
  eps->ops->solve                = EPSSolve_KRYLOVSCHUR;
373
  eps->ops->solvets              = PETSC_NULL;
374
  eps->ops->setup                = EPSSetUp_KRYLOVSCHUR;
375
  eps->ops->setfromoptions       = PETSC_NULL;
376
  eps->ops->destroy              = EPSDestroy_Default;
377
  eps->ops->view                 = PETSC_NULL;
378
  eps->ops->backtransform        = EPSBackTransform_Default;
379
  eps->ops->computevectors       = EPSComputeVectors_Schur;
380
  PetscFunctionReturn(0);
381
}
382
EXTERN_C_END
383