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
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
 
2283 jroman 42
#include <private/epsimpl.h>                /*I "slepceps.h" I*/
43
#include <slepcblaslapack.h>
1474 slepc 44
 
45
#undef __FUNCT__  
1542 slepc 46
#define __FUNCT__ "ArrowTridFlip"
47
/*
48
   ArrowTridFlip - Solves the arrowhead-tridiagonal eigenproblem by flipping
49
   the matrix and tridiagonalizing the bottom part.
50
 
51
   On input:
52
     l is the size of diagonal part
53
     d contains diagonal elements (length n)
54
     e contains offdiagonal elements (length n-1)
55
 
56
   On output:
57
     d contains the eigenvalues in ascending order
58
     Q is the eigenvector matrix (order n)
59
 
60
   Workspace:
61
     S is workspace to store a copy of the full matrix (nxn reals)
62
*/
1643 slepc 63
PetscErrorCode ArrowTridFlip(PetscInt n_,PetscInt l,PetscReal *d,PetscReal *e,PetscReal *Q,PetscReal *S)
1542 slepc 64
{
1548 slepc 65
#if defined(SLEPC_MISSING_LAPACK_SYTRD) || defined(SLEPC_MISSING_LAPACK_ORGTR) || defined(SLEPC_MISSING_LAPACK_STEQR)
66
  PetscFunctionBegin;
2214 jroman 67
  SETERRQ(PETSC_COMM_SELF,PETSC_ERR_SUP,"SYTRD/ORGTR/STEQR - Lapack routine is unavailable.");
1548 slepc 68
#else
1617 slepc 69
  PetscErrorCode ierr;
1542 slepc 70
  PetscInt       i,j;
1643 slepc 71
  PetscBLASInt   n,n1,n2,lwork,info;
1542 slepc 72
 
73
  PetscFunctionBegin;
1840 antodo 74
  ierr = PetscLogEventBegin(EPS_Dense,0,0,0,0);CHKERRQ(ierr);
1643 slepc 75
  n = PetscBLASIntCast(n_);
1718 antodo 76
  /* quick return */
77
  if (n == 1) {
78
    Q[0] = 1.0;
79
    PetscFunctionReturn(0);    
80
  }
1643 slepc 81
  n1 = PetscBLASIntCast(l+1);    /* size of leading block, including residuals */
82
  n2 = PetscBLASIntCast(n-l-1);  /* size of trailing block */
1617 slepc 83
  ierr = PetscMemzero(S,n*n*sizeof(PetscReal));CHKERRQ(ierr);
1542 slepc 84
 
85
  /* Flip matrix S, copying the values saved in Q */
86
  for (i=0;i<n;i++)
87
    S[(n-1-i)+(n-1-i)*n] = d[i];
88
  for (i=0;i<l;i++)
89
    S[(n-1-i)+(n-1-l)*n] = e[i];
1625 slepc 90
  for (i=l;i<n-1;i++)
1542 slepc 91
    S[(n-1-i)+(n-1-i-1)*n] = e[i];
92
 
93
  /* Reduce (2,2)-block of flipped S to tridiagonal form */
1643 slepc 94
  lwork = PetscBLASIntCast(n_*n_-n_);
1542 slepc 95
  LAPACKsytrd_("L",&n1,S+n2*(n+1),&n,d,e,Q,Q+n,&lwork,&info);
2214 jroman 96
  if (info) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_LIB,"Error in Lapack xSYTRD %d",info);
1542 slepc 97
 
98
  /* Flip back diag and subdiag, put them in d and e */
99
  for (i=0;i<n-1;i++) {
100
    d[n-i-1] = S[i+i*n];
101
    e[n-i-2] = S[i+1+i*n];
102
  }
103
  d[0] = S[n-1+(n-1)*n];
104
 
105
  /* Compute the orthogonal matrix used for tridiagonalization */
106
  LAPACKorgtr_("L",&n1,S+n2*(n+1),&n,Q,Q+n,&lwork,&info);
2214 jroman 107
  if (info) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_LIB,"Error in Lapack xORGTR %d",info);
1542 slepc 108
 
109
  /* Create full-size Q, flipped back to original order */
110
  for (i=0;i<n;i++)
111
    for (j=0;j<n;j++)
112
      Q[i+j*n] = 0.0;
113
  for (i=n1;i<n;i++)
114
    Q[i+i*n] = 1.0;
115
  for (i=0;i<n1;i++)
116
    for (j=0;j<n1;j++)
117
      Q[i+j*n] = S[n-i-1+(n-j-1)*n];
118
 
119
  /* Solve the tridiagonal eigenproblem */
120
  LAPACKsteqr_("V",&n,d,e,Q,&n,S,&info);
2214 jroman 121
  if (info) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_LIB,"Error in Lapack xSTEQR %d",info);
1542 slepc 122
 
1840 antodo 123
  ierr = PetscLogEventEnd(EPS_Dense,0,0,0,0);CHKERRQ(ierr);
1542 slepc 124
  PetscFunctionReturn(0);
1548 slepc 125
#endif
1542 slepc 126
}
127
 
128
#undef __FUNCT__  
1475 slepc 129
#define __FUNCT__ "EPSProjectedKSSym"
1474 slepc 130
/*
131
   EPSProjectedKSSym - Solves the projected eigenproblem in the Krylov-Schur
132
   method (symmetric case).
133
 
134
   On input:
1655 slepc 135
     n is the matrix dimension
136
     l is the number of vectors kept in previous restart
137
     a contains diagonal elements (length n)
138
     b contains offdiagonal elements (length n-1)
1474 slepc 139
 
140
   On output:
1477 slepc 141
     eig is the sorted list of eigenvalues
1655 slepc 142
     Q is the eigenvector matrix (order n, leading dimension n)
1474 slepc 143
 
144
   Workspace:
1655 slepc 145
     work is workspace to store a real square matrix of order n
146
     perm is workspace to store 2n integers
1474 slepc 147
*/
1655 slepc 148
PetscErrorCode EPSProjectedKSSym(EPS eps,PetscInt n,PetscInt l,PetscReal *a,PetscReal *b,PetscScalar *eig,PetscScalar *Q,PetscReal *work,PetscInt *perm)
1474 slepc 149
{
150
  PetscErrorCode ierr;
1655 slepc 151
  PetscInt       i,j,k,p;
152
  PetscReal      rtmp,*Qreal = (PetscReal*)Q;
1474 slepc 153
 
154
  PetscFunctionBegin;
1655 slepc 155
  /* Compute eigendecomposition of projected matrix */
156
  ierr = ArrowTridFlip(n,l,a,b,Qreal,work);CHKERRQ(ierr);
1477 slepc 157
 
1655 slepc 158
  /* Sort eigendecomposition according to eps->which */
1782 antodo 159
  ierr = EPSSortEigenvaluesReal(eps,n,a,perm);CHKERRQ(ierr);
1616 slepc 160
  for (i=0;i<n;i++)
1655 slepc 161
    eig[i] = a[perm[i]];
162
  for (i=0;i<n;i++) {
163
    p = perm[i];
164
    if (p != i) {
165
      j = i + 1;
166
      while (perm[j] != i) j++;
167
      perm[j] = p; perm[i] = i;
168
      /* swap eigenvectors i and j */
169
      for (k=0;k<n;k++) {
1669 slepc 170
        rtmp = Qreal[k+p*n]; Qreal[k+p*n] = Qreal[k+i*n]; Qreal[k+i*n] = rtmp;
1655 slepc 171
      }
172
    }
173
  }
174
 
1542 slepc 175
#if defined(PETSC_USE_COMPLEX)
1616 slepc 176
  for (j=n-1;j>=0;j--)
177
    for (i=n-1;i>=0;i--)
178
      Q[i+j*n] = Qreal[i+j*n];
1542 slepc 179
#endif
1474 slepc 180
  PetscFunctionReturn(0);
181
}
182
 
183
#undef __FUNCT__  
184
#define __FUNCT__ "EPSSolve_KRYLOVSCHUR_SYMM"
185
PetscErrorCode EPSSolve_KRYLOVSCHUR_SYMM(EPS eps)
186
{
187
  PetscErrorCode ierr;
2317 jroman 188
  PetscInt       i,k,l,lds,lt,nv,m,*iwork;
1755 antodo 189
  Vec            u=eps->work[0];
2059 jroman 190
  PetscScalar    *Q;
191
  PetscReal      *a,*b,*work,beta;
2216 jroman 192
  PetscBool      breakdown;
1474 slepc 193
 
194
  PetscFunctionBegin;
1691 slepc 195
  lds = PetscMin(eps->mpd,eps->ncv);
1655 slepc 196
  ierr = PetscMalloc(lds*lds*sizeof(PetscReal),&work);CHKERRQ(ierr);
2062 jroman 197
  ierr = PetscMalloc(lds*lds*sizeof(PetscScalar),&Q);CHKERRQ(ierr);
1655 slepc 198
  ierr = PetscMalloc(2*lds*sizeof(PetscInt),&iwork);CHKERRQ(ierr);
1691 slepc 199
  lt = PetscMin(eps->nev+eps->mpd,eps->ncv);
200
  ierr = PetscMalloc(lt*sizeof(PetscReal),&a);CHKERRQ(ierr);  
201
  ierr = PetscMalloc(lt*sizeof(PetscReal),&b);CHKERRQ(ierr);  
1474 slepc 202
 
1610 slepc 203
  /* Get the starting Lanczos vector */
1474 slepc 204
  ierr = EPSGetStartVector(eps,0,eps->V[0],PETSC_NULL);CHKERRQ(ierr);
205
  l = 0;
206
 
207
  /* Restart loop */
208
  while (eps->reason == EPS_CONVERGED_ITERATING) {
209
    eps->its++;
210
 
1610 slepc 211
    /* Compute an nv-step Lanczos factorization */
1622 slepc 212
    m = PetscMin(eps->nconv+eps->mpd,eps->ncv);
1655 slepc 213
    ierr = EPSFullLanczos(eps,a+l,b+l,eps->V,eps->nconv+l,&m,u,&breakdown);CHKERRQ(ierr);
1830 antodo 214
    nv = m - eps->nconv;
215
    beta = b[nv-1];
1474 slepc 216
 
217
    /* Solve projected problem and compute residual norm estimates */
1830 antodo 218
    ierr = EPSProjectedKSSym(eps,nv,l,a,b,eps->eigr+eps->nconv,Q,work,iwork);CHKERRQ(ierr);
1474 slepc 219
 
220
    /* Check convergence */
2059 jroman 221
    ierr = EPSKrylovConvergence(eps,PETSC_TRUE,eps->nconv,nv,PETSC_NULL,nv,Q,eps->V+eps->nconv,nv,beta,1.0,&k,PETSC_NULL);CHKERRQ(ierr);
1474 slepc 222
    if (eps->its >= eps->max_it) eps->reason = EPS_DIVERGED_ITS;
223
    if (k >= eps->nev) eps->reason = EPS_CONVERGED_TOL;
224
 
225
    /* Update l */
226
    if (eps->reason != EPS_CONVERGED_ITERATING || breakdown) l = 0;
1830 antodo 227
    else l = (eps->nconv+nv-k)/2;
1574 slepc 228
 
1474 slepc 229
    if (eps->reason == EPS_CONVERGED_ITERATING) {
230
      if (breakdown) {
1610 slepc 231
        /* Start a new Lanczos factorization */
1474 slepc 232
        PetscInfo2(eps,"Breakdown in Krylov-Schur method (it=%i norm=%g)\n",eps->its,beta);
233
        ierr = EPSGetStartVector(eps,k,eps->V[k],&breakdown);CHKERRQ(ierr);
234
        if (breakdown) {
235
          eps->reason = EPS_DIVERGED_BREAKDOWN;
236
          PetscInfo(eps,"Unable to generate more start vectors\n");
237
        }
238
      } else {
239
        /* Prepare the Rayleigh quotient for restart */
1612 slepc 240
        for (i=0;i<l;i++) {
1682 slepc 241
          a[i] = PetscRealPart(eps->eigr[i+k]);
1830 antodo 242
          b[i] = PetscRealPart(Q[nv-1+(i+k-eps->nconv)*nv]*beta);
1474 slepc 243
        }
244
      }
245
    }
246
    /* Update the corresponding vectors V(:,idx) = V*Q(:,idx) */
1830 antodo 247
    ierr = SlepcUpdateVectors(nv,eps->V+eps->nconv,0,k+l-eps->nconv,Q,nv,PETSC_FALSE);CHKERRQ(ierr);
1475 slepc 248
    /* Normalize u and append it to V */
1474 slepc 249
    if (eps->reason == EPS_CONVERGED_ITERATING && !breakdown) {
1475 slepc 250
      ierr = VecAXPBY(eps->V[k+l],1.0/beta,0.0,u);CHKERRQ(ierr);
1474 slepc 251
    }
1610 slepc 252
 
2313 jroman 253
    ierr = EPSMonitor(eps,eps->its,k,eps->eigr,eps->eigi,eps->errest,nv+eps->nconv);CHKERRQ(ierr);
1474 slepc 254
    eps->nconv = k;
255
  }
2062 jroman 256
  ierr = PetscFree(Q);CHKERRQ(ierr);
1622 slepc 257
  ierr = PetscFree(a);CHKERRQ(ierr);
258
  ierr = PetscFree(b);CHKERRQ(ierr);
1474 slepc 259
  ierr = PetscFree(work);CHKERRQ(ierr);
1655 slepc 260
  ierr = PetscFree(iwork);CHKERRQ(ierr);
1474 slepc 261
  PetscFunctionReturn(0);
262
}
263