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
 
2404 jroman 5
   Method: Krylov-Schur for symmetric eigenproblems
1474 slepc 6
 
7
   - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
1672 slepc 8
   SLEPc - Scalable Library for Eigenvalue Problem Computations
2575 eromero 9
   Copyright (c) 2002-2011, Universitat Politecnica de Valencia, Spain
1474 slepc 10
 
1672 slepc 11
   This file is part of SLEPc.
12
 
13
   SLEPc is free software: you can redistribute it and/or modify it under  the
14
   terms of version 3 of the GNU Lesser General Public License as published by
15
   the Free Software Foundation.
16
 
17
   SLEPc  is  distributed in the hope that it will be useful, but WITHOUT  ANY
18
   WARRANTY;  without even the implied warranty of MERCHANTABILITY or  FITNESS
19
   FOR  A  PARTICULAR PURPOSE. See the GNU Lesser General Public  License  for
20
   more details.
21
 
22
   You  should have received a copy of the GNU Lesser General  Public  License
23
   along with SLEPc. If not, see <http://www.gnu.org/licenses/>.
1474 slepc 24
   - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
25
*/
26
 
2729 jroman 27
#include <slepc-private/epsimpl.h>                /*I "slepceps.h" I*/
2283 jroman 28
#include <slepcblaslapack.h>
1474 slepc 29
 
30
#undef __FUNCT__  
1542 slepc 31
#define __FUNCT__ "ArrowTridFlip"
32
/*
33
   ArrowTridFlip - Solves the arrowhead-tridiagonal eigenproblem by flipping
34
   the matrix and tridiagonalizing the bottom part.
35
 
36
   On input:
37
     l is the size of diagonal part
38
     d contains diagonal elements (length n)
39
     e contains offdiagonal elements (length n-1)
40
 
41
   On output:
42
     d contains the eigenvalues in ascending order
43
     Q is the eigenvector matrix (order n)
44
 
45
   Workspace:
46
     S is workspace to store a copy of the full matrix (nxn reals)
47
*/
2723 jroman 48
static PetscErrorCode ArrowTridFlip(PetscInt n_,PetscInt l,PetscReal *d,PetscReal *e,PetscReal *Q,PetscReal *S)
1542 slepc 49
{
1548 slepc 50
#if defined(SLEPC_MISSING_LAPACK_SYTRD) || defined(SLEPC_MISSING_LAPACK_ORGTR) || defined(SLEPC_MISSING_LAPACK_STEQR)
51
  PetscFunctionBegin;
2214 jroman 52
  SETERRQ(PETSC_COMM_SELF,PETSC_ERR_SUP,"SYTRD/ORGTR/STEQR - Lapack routine is unavailable.");
1548 slepc 53
#else
1617 slepc 54
  PetscErrorCode ierr;
1542 slepc 55
  PetscInt       i,j;
1643 slepc 56
  PetscBLASInt   n,n1,n2,lwork,info;
1542 slepc 57
 
58
  PetscFunctionBegin;
1840 antodo 59
  ierr = PetscLogEventBegin(EPS_Dense,0,0,0,0);CHKERRQ(ierr);
1643 slepc 60
  n = PetscBLASIntCast(n_);
1718 antodo 61
  /* quick return */
62
  if (n == 1) {
63
    Q[0] = 1.0;
64
    PetscFunctionReturn(0);    
65
  }
1643 slepc 66
  n1 = PetscBLASIntCast(l+1);    /* size of leading block, including residuals */
67
  n2 = PetscBLASIntCast(n-l-1);  /* size of trailing block */
1617 slepc 68
  ierr = PetscMemzero(S,n*n*sizeof(PetscReal));CHKERRQ(ierr);
2740 jroman 69
  ierr = PetscFPTrapPush(PETSC_FP_TRAP_OFF);CHKERRQ(ierr);
1542 slepc 70
 
71
  /* Flip matrix S, copying the values saved in Q */
72
  for (i=0;i<n;i++)
73
    S[(n-1-i)+(n-1-i)*n] = d[i];
74
  for (i=0;i<l;i++)
75
    S[(n-1-i)+(n-1-l)*n] = e[i];
1625 slepc 76
  for (i=l;i<n-1;i++)
1542 slepc 77
    S[(n-1-i)+(n-1-i-1)*n] = e[i];
78
 
79
  /* Reduce (2,2)-block of flipped S to tridiagonal form */
1643 slepc 80
  lwork = PetscBLASIntCast(n_*n_-n_);
1542 slepc 81
  LAPACKsytrd_("L",&n1,S+n2*(n+1),&n,d,e,Q,Q+n,&lwork,&info);
2214 jroman 82
  if (info) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_LIB,"Error in Lapack xSYTRD %d",info);
1542 slepc 83
 
84
  /* Flip back diag and subdiag, put them in d and e */
85
  for (i=0;i<n-1;i++) {
86
    d[n-i-1] = S[i+i*n];
87
    e[n-i-2] = S[i+1+i*n];
88
  }
89
  d[0] = S[n-1+(n-1)*n];
90
 
91
  /* Compute the orthogonal matrix used for tridiagonalization */
92
  LAPACKorgtr_("L",&n1,S+n2*(n+1),&n,Q,Q+n,&lwork,&info);
2214 jroman 93
  if (info) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_LIB,"Error in Lapack xORGTR %d",info);
1542 slepc 94
 
95
  /* Create full-size Q, flipped back to original order */
96
  for (i=0;i<n;i++)
97
    for (j=0;j<n;j++)
98
      Q[i+j*n] = 0.0;
99
  for (i=n1;i<n;i++)
100
    Q[i+i*n] = 1.0;
101
  for (i=0;i<n1;i++)
102
    for (j=0;j<n1;j++)
103
      Q[i+j*n] = S[n-i-1+(n-j-1)*n];
104
 
105
  /* Solve the tridiagonal eigenproblem */
106
  LAPACKsteqr_("V",&n,d,e,Q,&n,S,&info);
2214 jroman 107
  if (info) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_LIB,"Error in Lapack xSTEQR %d",info);
1542 slepc 108
 
2740 jroman 109
  ierr = PetscFPTrapPop();CHKERRQ(ierr);
1840 antodo 110
  ierr = PetscLogEventEnd(EPS_Dense,0,0,0,0);CHKERRQ(ierr);
1542 slepc 111
  PetscFunctionReturn(0);
1548 slepc 112
#endif
1542 slepc 113
}
114
 
115
#undef __FUNCT__  
1475 slepc 116
#define __FUNCT__ "EPSProjectedKSSym"
1474 slepc 117
/*
118
   EPSProjectedKSSym - Solves the projected eigenproblem in the Krylov-Schur
119
   method (symmetric case).
120
 
121
   On input:
1655 slepc 122
     n is the matrix dimension
123
     l is the number of vectors kept in previous restart
124
     a contains diagonal elements (length n)
125
     b contains offdiagonal elements (length n-1)
1474 slepc 126
 
127
   On output:
1477 slepc 128
     eig is the sorted list of eigenvalues
1655 slepc 129
     Q is the eigenvector matrix (order n, leading dimension n)
1474 slepc 130
 
131
   Workspace:
1655 slepc 132
     work is workspace to store a real square matrix of order n
133
     perm is workspace to store 2n integers
1474 slepc 134
*/
1655 slepc 135
PetscErrorCode EPSProjectedKSSym(EPS eps,PetscInt n,PetscInt l,PetscReal *a,PetscReal *b,PetscScalar *eig,PetscScalar *Q,PetscReal *work,PetscInt *perm)
1474 slepc 136
{
137
  PetscErrorCode ierr;
1655 slepc 138
  PetscInt       i,j,k,p;
139
  PetscReal      rtmp,*Qreal = (PetscReal*)Q;
1474 slepc 140
 
141
  PetscFunctionBegin;
1655 slepc 142
  /* Compute eigendecomposition of projected matrix */
143
  ierr = ArrowTridFlip(n,l,a,b,Qreal,work);CHKERRQ(ierr);
1477 slepc 144
 
1655 slepc 145
  /* Sort eigendecomposition according to eps->which */
1782 antodo 146
  ierr = EPSSortEigenvaluesReal(eps,n,a,perm);CHKERRQ(ierr);
1616 slepc 147
  for (i=0;i<n;i++)
1655 slepc 148
    eig[i] = a[perm[i]];
149
  for (i=0;i<n;i++) {
150
    p = perm[i];
151
    if (p != i) {
152
      j = i + 1;
153
      while (perm[j] != i) j++;
154
      perm[j] = p; perm[i] = i;
155
      /* swap eigenvectors i and j */
156
      for (k=0;k<n;k++) {
1669 slepc 157
        rtmp = Qreal[k+p*n]; Qreal[k+p*n] = Qreal[k+i*n]; Qreal[k+i*n] = rtmp;
1655 slepc 158
      }
159
    }
160
  }
161
 
1542 slepc 162
#if defined(PETSC_USE_COMPLEX)
1616 slepc 163
  for (j=n-1;j>=0;j--)
164
    for (i=n-1;i>=0;i--)
165
      Q[i+j*n] = Qreal[i+j*n];
1542 slepc 166
#endif
1474 slepc 167
  PetscFunctionReturn(0);
168
}
169
 
170
#undef __FUNCT__  
2324 jroman 171
#define __FUNCT__ "EPSSolve_KrylovSchur_Symm"
172
PetscErrorCode EPSSolve_KrylovSchur_Symm(EPS eps)
1474 slepc 173
{
174
  PetscErrorCode ierr;
2317 jroman 175
  PetscInt       i,k,l,lds,lt,nv,m,*iwork;
1755 antodo 176
  Vec            u=eps->work[0];
2059 jroman 177
  PetscScalar    *Q;
178
  PetscReal      *a,*b,*work,beta;
2216 jroman 179
  PetscBool      breakdown;
1474 slepc 180
 
181
  PetscFunctionBegin;
1691 slepc 182
  lds = PetscMin(eps->mpd,eps->ncv);
1655 slepc 183
  ierr = PetscMalloc(lds*lds*sizeof(PetscReal),&work);CHKERRQ(ierr);
2062 jroman 184
  ierr = PetscMalloc(lds*lds*sizeof(PetscScalar),&Q);CHKERRQ(ierr);
1655 slepc 185
  ierr = PetscMalloc(2*lds*sizeof(PetscInt),&iwork);CHKERRQ(ierr);
1691 slepc 186
  lt = PetscMin(eps->nev+eps->mpd,eps->ncv);
187
  ierr = PetscMalloc(lt*sizeof(PetscReal),&a);CHKERRQ(ierr);  
188
  ierr = PetscMalloc(lt*sizeof(PetscReal),&b);CHKERRQ(ierr);  
1474 slepc 189
 
1610 slepc 190
  /* Get the starting Lanczos vector */
1474 slepc 191
  ierr = EPSGetStartVector(eps,0,eps->V[0],PETSC_NULL);CHKERRQ(ierr);
192
  l = 0;
193
 
194
  /* Restart loop */
195
  while (eps->reason == EPS_CONVERGED_ITERATING) {
196
    eps->its++;
197
 
1610 slepc 198
    /* Compute an nv-step Lanczos factorization */
1622 slepc 199
    m = PetscMin(eps->nconv+eps->mpd,eps->ncv);
1655 slepc 200
    ierr = EPSFullLanczos(eps,a+l,b+l,eps->V,eps->nconv+l,&m,u,&breakdown);CHKERRQ(ierr);
1830 antodo 201
    nv = m - eps->nconv;
202
    beta = b[nv-1];
1474 slepc 203
 
204
    /* Solve projected problem and compute residual norm estimates */
1830 antodo 205
    ierr = EPSProjectedKSSym(eps,nv,l,a,b,eps->eigr+eps->nconv,Q,work,iwork);CHKERRQ(ierr);
1474 slepc 206
 
207
    /* Check convergence */
2583 jroman 208
    ierr = EPSKrylovConvergence(eps,PETSC_TRUE,eps->trackall,eps->nconv,nv,PETSC_NULL,nv,Q,eps->V+eps->nconv,nv,beta,1.0,&k,PETSC_NULL);CHKERRQ(ierr);
1474 slepc 209
    if (eps->its >= eps->max_it) eps->reason = EPS_DIVERGED_ITS;
210
    if (k >= eps->nev) eps->reason = EPS_CONVERGED_TOL;
211
 
212
    /* Update l */
213
    if (eps->reason != EPS_CONVERGED_ITERATING || breakdown) l = 0;
1830 antodo 214
    else l = (eps->nconv+nv-k)/2;
1574 slepc 215
 
1474 slepc 216
    if (eps->reason == EPS_CONVERGED_ITERATING) {
217
      if (breakdown) {
1610 slepc 218
        /* Start a new Lanczos factorization */
2499 jroman 219
        ierr = PetscInfo2(eps,"Breakdown in Krylov-Schur method (it=%D norm=%G)\n",eps->its,beta);CHKERRQ(ierr);
1474 slepc 220
        ierr = EPSGetStartVector(eps,k,eps->V[k],&breakdown);CHKERRQ(ierr);
221
        if (breakdown) {
222
          eps->reason = EPS_DIVERGED_BREAKDOWN;
2499 jroman 223
          ierr = PetscInfo(eps,"Unable to generate more start vectors\n");CHKERRQ(ierr);
1474 slepc 224
        }
225
      } else {
226
        /* Prepare the Rayleigh quotient for restart */
1612 slepc 227
        for (i=0;i<l;i++) {
1682 slepc 228
          a[i] = PetscRealPart(eps->eigr[i+k]);
1830 antodo 229
          b[i] = PetscRealPart(Q[nv-1+(i+k-eps->nconv)*nv]*beta);
1474 slepc 230
        }
231
      }
232
    }
233
    /* Update the corresponding vectors V(:,idx) = V*Q(:,idx) */
1830 antodo 234
    ierr = SlepcUpdateVectors(nv,eps->V+eps->nconv,0,k+l-eps->nconv,Q,nv,PETSC_FALSE);CHKERRQ(ierr);
1475 slepc 235
    /* Normalize u and append it to V */
1474 slepc 236
    if (eps->reason == EPS_CONVERGED_ITERATING && !breakdown) {
1475 slepc 237
      ierr = VecAXPBY(eps->V[k+l],1.0/beta,0.0,u);CHKERRQ(ierr);
1474 slepc 238
    }
1610 slepc 239
 
2313 jroman 240
    ierr = EPSMonitor(eps,eps->its,k,eps->eigr,eps->eigi,eps->errest,nv+eps->nconv);CHKERRQ(ierr);
1474 slepc 241
    eps->nconv = k;
242
  }
2062 jroman 243
  ierr = PetscFree(Q);CHKERRQ(ierr);
1622 slepc 244
  ierr = PetscFree(a);CHKERRQ(ierr);
245
  ierr = PetscFree(b);CHKERRQ(ierr);
1474 slepc 246
  ierr = PetscFree(work);CHKERRQ(ierr);
1655 slepc 247
  ierr = PetscFree(iwork);CHKERRQ(ierr);
1474 slepc 248
  PetscFunctionReturn(0);
249
}
250