Subversion Repositories slepc-dev

Rev

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
2116 eromero 24
   Copyright (c) 2002-2010, 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__ "EPSSolve_KRYLOVSCHUR_HARMONIC"
172
PetscErrorCode EPSSolve_KRYLOVSCHUR_HARMONIC(EPS eps)
173
{
174
  PetscErrorCode ierr;
2059 jroman 175
  PetscInt       i,k,l,lwork,nv;
1755 antodo 176
  Vec            u=eps->work[0];
2059 jroman 177
  PetscScalar    *S=eps->T,*Q,*g,*work;
178
  PetscReal      beta,gnorm;
179
  PetscTruth     breakdown;
1498 slepc 180
 
181
  PetscFunctionBegin;
182
  ierr = PetscMemzero(S,eps->ncv*eps->ncv*sizeof(PetscScalar));CHKERRQ(ierr);
1830 antodo 183
  ierr = PetscMalloc(eps->ncv*eps->ncv*sizeof(PetscScalar),&Q);CHKERRQ(ierr);
2057 jroman 184
  lwork = PetscMax((eps->ncv+1)*eps->ncv,7*eps->ncv);
1498 slepc 185
  ierr = PetscMalloc(lwork*sizeof(PetscScalar),&work);CHKERRQ(ierr);
186
  ierr = PetscMalloc(eps->ncv*sizeof(PetscScalar),&g);CHKERRQ(ierr);
187
 
188
  /* Get the starting Arnoldi vector */
189
  ierr = EPSGetStartVector(eps,0,eps->V[0],PETSC_NULL);CHKERRQ(ierr);
190
  l = 0;
191
 
192
  /* Restart loop */
193
  while (eps->reason == EPS_CONVERGED_ITERATING) {
194
    eps->its++;
195
 
196
    /* Compute an nv-step Arnoldi factorization */
1830 antodo 197
    nv = PetscMin(eps->nconv+eps->mpd,eps->ncv);
198
    ierr = EPSBasicArnoldi(eps,PETSC_FALSE,S,eps->ncv,eps->V,eps->nconv+l,&nv,u,&beta,&breakdown);CHKERRQ(ierr);
1498 slepc 199
    ierr = VecScale(u,1.0/beta);CHKERRQ(ierr);
200
 
1574 slepc 201
    /* Compute translation of Krylov decomposition */
1830 antodo 202
    ierr = EPSTranslateHarmonic(nv,S,eps->ncv,eps->target,(PetscScalar)beta,g,work);CHKERRQ(ierr);
2026 jroman 203
    gnorm = 0.0;
204
    for (i=0;i<nv;i++)
205
      gnorm = gnorm + PetscRealPart(g[i]*PetscConj(g[i]));
1498 slepc 206
 
207
    /* Solve projected problem and compute residual norm estimates */
2099 jroman 208
    ierr = EPSProjectedKSNonsym(eps,l,S,eps->ncv,Q,nv);CHKERRQ(ierr);
1498 slepc 209
 
2059 jroman 210
    /* Check convergence */
211
    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 212
    if (eps->its >= eps->max_it) eps->reason = EPS_DIVERGED_ITS;
213
    if (k >= eps->nev) eps->reason = EPS_CONVERGED_TOL;
214
 
215
    /* Update l */
216
    if (eps->reason != EPS_CONVERGED_ITERATING || breakdown) l = 0;
217
    else {
1830 antodo 218
      l = (nv-k)/2;
1498 slepc 219
#if !defined(PETSC_USE_COMPLEX)
220
      if (S[(k+l-1)*(eps->ncv+1)+1] != 0.0) {
1830 antodo 221
        if (k+l<nv-1) l = l+1;
1498 slepc 222
        else l = l-1;
223
      }
224
#endif
225
    }
226
 
227
    if (eps->reason == EPS_CONVERGED_ITERATING) {
228
      if (breakdown) {
229
        /* Start a new Arnoldi factorization */
230
        PetscInfo2(eps,"Breakdown in Krylov-Schur method (it=%i norm=%g)\n",eps->its,beta);
231
        ierr = EPSGetStartVector(eps,k,eps->V[k],&breakdown);CHKERRQ(ierr);
232
        if (breakdown) {
233
          eps->reason = EPS_DIVERGED_BREAKDOWN;
234
          PetscInfo(eps,"Unable to generate more start vectors\n");
235
        }
236
      } else {
237
        /* Prepare the Rayleigh quotient for restart */
238
        for (i=k;i<k+l;i++) {
1830 antodo 239
          S[i*eps->ncv+k+l] = Q[(i+1)*nv-1]*beta;
1498 slepc 240
        }
1830 antodo 241
        ierr = EPSRecoverHarmonic(S,nv,k,l,eps->ncv,g,Q,eps->V,u,work);CHKERRQ(ierr);
1498 slepc 242
      }
243
    }
244
    /* Update the corresponding vectors V(:,idx) = V*Q(:,idx) */
1830 antodo 245
    ierr = SlepcUpdateVectors(nv,eps->V,eps->nconv,k+l,Q,nv,PETSC_FALSE);CHKERRQ(ierr);
1582 slepc 246
 
1498 slepc 247
    if (eps->reason == EPS_CONVERGED_ITERATING && !breakdown) {
248
      ierr = VecCopy(u,eps->V[k+l]);CHKERRQ(ierr);
249
    }
250
    eps->nconv = k;
251
 
1830 antodo 252
    EPSMonitor(eps,eps->its,eps->nconv,eps->eigr,eps->eigi,eps->errest,nv);
1498 slepc 253
 
254
  }
255
 
2057 jroman 256
  ierr = PetscFree(Q);CHKERRQ(ierr);
1498 slepc 257
  ierr = PetscFree(work);CHKERRQ(ierr);
258
  ierr = PetscFree(g);CHKERRQ(ierr);
259
  PetscFunctionReturn(0);
260
}
261