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
1474 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
 
1673 slepc 20
   Last update: Feb 2009
1474 slepc 21
 
22
   - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
1672 slepc 23
   SLEPc - Scalable Library for Eigenvalue Problem Computations
24
   Copyright (c) 2002-2009, Universidad Politecnica de Valencia, Spain
1474 slepc 25
 
1672 slepc 26
   This file is part of SLEPc.
27
 
28
   SLEPc is free software: you can redistribute it and/or modify it under  the
29
   terms of version 3 of the GNU Lesser General Public License as published by
30
   the Free Software Foundation.
31
 
32
   SLEPc  is  distributed in the hope that it will be useful, but WITHOUT  ANY
33
   WARRANTY;  without even the implied warranty of MERCHANTABILITY or  FITNESS
34
   FOR  A  PARTICULAR PURPOSE. See the GNU Lesser General Public  License  for
35
   more details.
36
 
37
   You  should have received a copy of the GNU Lesser General  Public  License
38
   along with SLEPc. If not, see <http://www.gnu.org/licenses/>.
1474 slepc 39
   - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
40
*/
41
 
1521 slepc 42
#include "private/epsimpl.h"                /*I "slepceps.h" I*/
1474 slepc 43
#include "slepcblaslapack.h"
44
 
45
#undef __FUNCT__  
46
#define __FUNCT__ "EPSTranslateHarmonic"
47
/*
48
   EPSTranslateHarmonic - Computes a translation of the Krylov decomposition
1560 slepc 49
   in order to perform a harmonic extraction.
1474 slepc 50
 
51
   On input:
1663 slepc 52
     S is the Rayleigh quotient (order m, leading dimension is lds)
1474 slepc 53
     tau is the translation amount
54
     b is assumed to be beta*e_m^T
55
 
56
   On output:
57
     g = (B-sigma*eye(m))'\b
58
     S is updated as S + g*b'
59
 
60
   Workspace:
1498 slepc 61
     work is workspace to store a working copy of S and the pivots (int
62
     of length m)
1474 slepc 63
*/
1663 slepc 64
PetscErrorCode EPSTranslateHarmonic(PetscInt m_,PetscScalar *S,PetscInt lds,PetscScalar tau,PetscScalar beta,PetscScalar *g,PetscScalar *work)
1474 slepc 65
{
66
#if defined(PETSC_MISSING_LAPACK_GETRF) || defined(PETSC_MISSING_LAPACK_GETRS)
67
  PetscFunctionBegin;
68
  SETERRQ(PETSC_ERR_SUP,"GETRF,GETRS - Lapack routines are unavailable.");
69
#else
70
  PetscErrorCode ierr;
1663 slepc 71
  PetscInt       i,j;
1664 slepc 72
  PetscBLASInt   info,m,one = 1;
1474 slepc 73
  PetscScalar    *B = work;
1681 slepc 74
  PetscBLASInt   *ipiv = (PetscBLASInt*)(work+m_*m_);
1474 slepc 75
 
76
  PetscFunctionBegin;
1664 slepc 77
  m = PetscBLASIntCast(m_);
1474 slepc 78
  /* Copy S to workspace B */
1663 slepc 79
  for (i=0;i<m;i++)
80
    for (j=0;j<m;j++)
81
      B[i+j*m] = S[i+j*lds];
1474 slepc 82
  /* Vector g initialy stores b */
83
  ierr = PetscMemzero(g,m*sizeof(PetscScalar));CHKERRQ(ierr);
84
  g[m-1] = beta;
85
 
86
  /* g = (B-sigma*eye(m))'\b */
87
  for (i=0;i<m;i++)
88
    B[i+i*m] -= tau;
89
  LAPACKgetrf_(&m,&m,B,&m,ipiv,&info);
90
  if (info<0) SETERRQ(PETSC_ERR_LIB,"Bad argument to LU factorization");
91
  if (info>0) SETERRQ(PETSC_ERR_MAT_LU_ZRPVT,"Bad LU factorization");
1720 antodo 92
  ierr = PetscLogFlops(2.0*m*m*m/3.0);CHKERRQ(ierr);
1474 slepc 93
  LAPACKgetrs_("C",&m,&one,B,&m,ipiv,g,&m,&info);
94
  if (info) SETERRQ(PETSC_ERR_LIB,"GETRS - Bad solve");
1720 antodo 95
  ierr = PetscLogFlops(2.0*m*m-m);CHKERRQ(ierr);
1474 slepc 96
 
97
  /* S = S + g*b' */
98
  for (i=0;i<m;i++)
1663 slepc 99
    S[i+(m-1)*lds] = S[i+(m-1)*lds] + g[i]*beta;
1474 slepc 100
 
101
  PetscFunctionReturn(0);
102
#endif
103
}
104
 
105
#undef __FUNCT__  
106
#define __FUNCT__ "EPSRecoverHarmonic"
107
/*
1498 slepc 108
   EPSRecoverHarmonic - Computes a translation of the truncated Krylov
109
   decomposition in order to recover the original non-translated state
1474 slepc 110
 
111
   On input:
112
     S is the truncated Rayleigh quotient (size n, leading dimension m)
113
     k and l indicate the active columns of S
114
     [U, u] is the basis of the Krylov subspace
115
     g is the vector computed in the original translation
116
     Q is the similarity transformation used to reduce to sorted Schur form
117
 
118
   On output:
119
     S is updated as S + g*b'
120
     u is re-orthonormalized with respect to U
121
     b is re-scaled
122
     g is destroyed
123
 
124
   Workspace:
125
     ghat is workspace to store a vector of length n
126
*/
1509 slepc 127
PetscErrorCode EPSRecoverHarmonic(PetscScalar *S,PetscInt n_,PetscInt k,PetscInt l,PetscInt m_,PetscScalar *g,PetscScalar *Q,Vec *U,Vec u,PetscScalar *ghat)
1474 slepc 128
{
129
  PetscFunctionBegin;
130
  PetscErrorCode ierr;
1664 slepc 131
  PetscBLASInt   one=1,ncol=k+l,n,m;
1474 slepc 132
  PetscScalar    done=1.0,dmone=-1.0,dzero=0.0;
133
  PetscReal      gamma,gnorm;
1509 slepc 134
  PetscBLASInt   i,j;
1474 slepc 135
 
136
  PetscFunctionBegin;
1664 slepc 137
  n = PetscBLASIntCast(n_);
138
  m = PetscBLASIntCast(m_);
1474 slepc 139
 
140
  /* g^ = -Q(:,idx)'*g */
1663 slepc 141
  BLASgemv_("C",&n,&ncol,&dmone,Q,&n,g,&one,&dzero,ghat,&one);
1474 slepc 142
 
143
  /* S = S + g^*b' */
1487 slepc 144
  for (i=0;i<k+l;i++) {
1474 slepc 145
    for (j=k;j<k+l;j++) {
146
      S[i+j*m] += ghat[i]*S[k+l+j*m];
147
    }
148
  }
149
 
150
  /* g~ = (I-Q(:,idx)*Q(:,idx)')*g = g+Q(:,idx)*g^ */
1663 slepc 151
  BLASgemv_("N",&n,&ncol,&done,Q,&n,ghat,&one,&done,g,&one);
1474 slepc 152
 
153
  /* gamma u^ = u - U*g~ */
1755 antodo 154
  ierr = SlepcVecMAXPBY(u,1.0,-1.0,m,g,U);CHKERRQ(ierr);        
1474 slepc 155
 
156
  /* Renormalize u */
157
  gnorm = 0.0;
158
  for (i=0;i<n;i++)
1482 slepc 159
    gnorm = gnorm + PetscRealPart(g[i]*PetscConj(g[i]));
1474 slepc 160
  gamma = sqrt(1.0+gnorm);
161
  ierr = VecScale(u,1.0/gamma);CHKERRQ(ierr);
162
 
163
  /* b = gamma*b */
164
  for (i=k;i<k+l;i++) {
165
    S[i*m+k+l] *= gamma;
166
  }
167
  PetscFunctionReturn(0);
168
}
169
 
1498 slepc 170
#undef __FUNCT__  
171
#define __FUNCT__ "EPSProjectedKSHarmonic"
172
/*
173
   EPSProjectedKSHarmonic - Solves the projected eigenproblem in the
174
   Krylov-Schur method (non-symmetric harmonic case).
175
 
176
   On input:
177
     l is the number of vectors kept in previous restart (0 means first restart)
178
     S is the projected matrix (leading dimension is lds)
179
 
180
   On output:
181
     S has (real) Schur form with diagonal blocks sorted appropriately
182
     Q contains the corresponding Schur vectors (order n, leading dimension n)
183
*/
1509 slepc 184
PetscErrorCode EPSProjectedKSHarmonic(EPS eps,PetscInt l,PetscScalar *S,PetscInt lds,PetscScalar *Q,PetscInt n)
1498 slepc 185
{
186
  PetscErrorCode ierr;
187
 
188
  PetscFunctionBegin;
189
  /* Reduce S to Hessenberg form, S <- Q S Q' */
190
  ierr = EPSDenseHessenberg(n,eps->nconv,S,lds,Q);CHKERRQ(ierr);
191
  /* Reduce S to (quasi-)triangular form, S <- Q S Q' */
192
  ierr = EPSDenseSchur(n,eps->nconv,S,lds,Q,eps->eigr,eps->eigi);CHKERRQ(ierr);
193
  /* Sort the remaining columns of the Schur form */
1823 antodo 194
  ierr = EPSSortDenseSchur(eps,n,eps->nconv,S,lds,Q,eps->eigr,eps->eigi);CHKERRQ(ierr);
1498 slepc 195
  PetscFunctionReturn(0);
196
}
197
 
198
#undef __FUNCT__  
199
#define __FUNCT__ "EPSSolve_KRYLOVSCHUR_HARMONIC"
200
PetscErrorCode EPSSolve_KRYLOVSCHUR_HARMONIC(EPS eps)
201
{
202
  PetscErrorCode ierr;
2059 jroman 203
  PetscInt       i,k,l,lwork,nv;
1755 antodo 204
  Vec            u=eps->work[0];
2059 jroman 205
  PetscScalar    *S=eps->T,*Q,*g,*work;
206
  PetscReal      beta,gnorm;
207
  PetscTruth     breakdown;
1498 slepc 208
 
209
  PetscFunctionBegin;
210
  ierr = PetscMemzero(S,eps->ncv*eps->ncv*sizeof(PetscScalar));CHKERRQ(ierr);
1830 antodo 211
  ierr = PetscMalloc(eps->ncv*eps->ncv*sizeof(PetscScalar),&Q);CHKERRQ(ierr);
2057 jroman 212
  lwork = PetscMax((eps->ncv+1)*eps->ncv,7*eps->ncv);
1498 slepc 213
  ierr = PetscMalloc(lwork*sizeof(PetscScalar),&work);CHKERRQ(ierr);
214
  ierr = PetscMalloc(eps->ncv*sizeof(PetscScalar),&g);CHKERRQ(ierr);
215
 
216
  /* Get the starting Arnoldi vector */
217
  ierr = EPSGetStartVector(eps,0,eps->V[0],PETSC_NULL);CHKERRQ(ierr);
218
  l = 0;
219
 
220
  /* Restart loop */
221
  while (eps->reason == EPS_CONVERGED_ITERATING) {
222
    eps->its++;
223
 
224
    /* Compute an nv-step Arnoldi factorization */
1830 antodo 225
    nv = PetscMin(eps->nconv+eps->mpd,eps->ncv);
226
    ierr = EPSBasicArnoldi(eps,PETSC_FALSE,S,eps->ncv,eps->V,eps->nconv+l,&nv,u,&beta,&breakdown);CHKERRQ(ierr);
1498 slepc 227
    ierr = VecScale(u,1.0/beta);CHKERRQ(ierr);
228
 
1574 slepc 229
    /* Compute translation of Krylov decomposition */
1830 antodo 230
    ierr = EPSTranslateHarmonic(nv,S,eps->ncv,eps->target,(PetscScalar)beta,g,work);CHKERRQ(ierr);
2026 jroman 231
    gnorm = 0.0;
232
    for (i=0;i<nv;i++)
233
      gnorm = gnorm + PetscRealPart(g[i]*PetscConj(g[i]));
1498 slepc 234
 
235
    /* Solve projected problem and compute residual norm estimates */
1830 antodo 236
    ierr = EPSProjectedKSHarmonic(eps,l,S,eps->ncv,Q,nv);CHKERRQ(ierr);
1498 slepc 237
 
2059 jroman 238
    /* Check convergence */
239
    ierr = EPSKrylovConvergence(eps,PETSC_FALSE,eps->nconv,nv-eps->nconv,S,eps->ncv,Q,eps->V,nv,beta,sqrt(1.0+gnorm),&k,work);CHKERRQ(ierr);
1498 slepc 240
    if (eps->its >= eps->max_it) eps->reason = EPS_DIVERGED_ITS;
241
    if (k >= eps->nev) eps->reason = EPS_CONVERGED_TOL;
242
 
243
    /* Update l */
244
    if (eps->reason != EPS_CONVERGED_ITERATING || breakdown) l = 0;
245
    else {
1830 antodo 246
      l = (nv-k)/2;
1498 slepc 247
#if !defined(PETSC_USE_COMPLEX)
248
      if (S[(k+l-1)*(eps->ncv+1)+1] != 0.0) {
1830 antodo 249
        if (k+l<nv-1) l = l+1;
1498 slepc 250
        else l = l-1;
251
      }
252
#endif
253
    }
254
 
255
    if (eps->reason == EPS_CONVERGED_ITERATING) {
256
      if (breakdown) {
257
        /* Start a new Arnoldi factorization */
258
        PetscInfo2(eps,"Breakdown in Krylov-Schur method (it=%i norm=%g)\n",eps->its,beta);
259
        ierr = EPSGetStartVector(eps,k,eps->V[k],&breakdown);CHKERRQ(ierr);
260
        if (breakdown) {
261
          eps->reason = EPS_DIVERGED_BREAKDOWN;
262
          PetscInfo(eps,"Unable to generate more start vectors\n");
263
        }
264
      } else {
265
        /* Prepare the Rayleigh quotient for restart */
266
        for (i=k;i<k+l;i++) {
1830 antodo 267
          S[i*eps->ncv+k+l] = Q[(i+1)*nv-1]*beta;
1498 slepc 268
        }
1830 antodo 269
        ierr = EPSRecoverHarmonic(S,nv,k,l,eps->ncv,g,Q,eps->V,u,work);CHKERRQ(ierr);
1498 slepc 270
      }
271
    }
272
    /* Update the corresponding vectors V(:,idx) = V*Q(:,idx) */
1830 antodo 273
    ierr = SlepcUpdateVectors(nv,eps->V,eps->nconv,k+l,Q,nv,PETSC_FALSE);CHKERRQ(ierr);
1582 slepc 274
 
1498 slepc 275
    if (eps->reason == EPS_CONVERGED_ITERATING && !breakdown) {
276
      ierr = VecCopy(u,eps->V[k+l]);CHKERRQ(ierr);
277
    }
278
    eps->nconv = k;
279
 
1830 antodo 280
    EPSMonitor(eps,eps->its,eps->nconv,eps->eigr,eps->eigi,eps->errest,nv);
1498 slepc 281
 
282
  }
283
 
2057 jroman 284
  ierr = PetscFree(Q);CHKERRQ(ierr);
1498 slepc 285
  ierr = PetscFree(work);CHKERRQ(ierr);
286
  ierr = PetscFree(g);CHKERRQ(ierr);
287
  PetscFunctionReturn(0);
288
}
289