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
 
1673 slepc 20
   Last update: Feb 2009
1217 slepc 21
 
1376 slepc 22
   - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
1672 slepc 23
   SLEPc - Scalable Library for Eigenvalue Problem Computations
24
   Copyright (c) 2002-2009, Universidad Politecnica de Valencia, Spain
1376 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/>.
1376 slepc 39
   - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
1217 slepc 40
*/
1376 slepc 41
 
1521 slepc 42
#include "private/epsimpl.h"                /*I "slepceps.h" I*/
1171 slepc 43
#include "slepcblaslapack.h"
44
 
1474 slepc 45
PetscErrorCode EPSSolve_KRYLOVSCHUR_DEFAULT(EPS eps);
1498 slepc 46
extern PetscErrorCode EPSSolve_KRYLOVSCHUR_HARMONIC(EPS eps);
1474 slepc 47
extern PetscErrorCode EPSSolve_KRYLOVSCHUR_SYMM(EPS eps);
48
 
1171 slepc 49
#undef __FUNCT__  
50
#define __FUNCT__ "EPSSetUp_KRYLOVSCHUR"
51
PetscErrorCode EPSSetUp_KRYLOVSCHUR(EPS eps)
52
{
53
  PetscErrorCode ierr;
1661 slepc 54
  PetscInt       N;
1171 slepc 55
 
56
  PetscFunctionBegin;
1385 slepc 57
  ierr = VecGetSize(eps->vec_initial,&N);CHKERRQ(ierr);
1576 slepc 58
  if (eps->ncv) { /* ncv set */
1718 antodo 59
    if (eps->ncv<eps->nev) SETERRQ(1,"The value of ncv must be at least nev");
1171 slepc 60
  }
1576 slepc 61
  else if (eps->mpd) { /* mpd set */
62
    eps->ncv = PetscMin(N,eps->nev+eps->mpd);
63
  }
64
  else { /* neither set: defaults depend on nev being small or large */
65
    if (eps->nev<500) eps->ncv = PetscMin(N,PetscMax(2*eps->nev,eps->nev+15));
66
    else { eps->mpd = 500; eps->ncv = PetscMin(N,eps->nev+eps->mpd); }
67
  }
68
  if (!eps->mpd) eps->mpd = eps->ncv;
69
  if (eps->ncv>eps->nev+eps->mpd) SETERRQ(1,"The value of ncv must not be larger than nev+mpd");
1220 slepc 70
  if (!eps->max_it) eps->max_it = PetscMax(100,2*N/eps->ncv);
1177 slepc 71
  if (eps->ishermitian && (eps->which==EPS_LARGEST_IMAGINARY || eps->which==EPS_SMALLEST_IMAGINARY))
72
    SETERRQ(1,"Wrong value of eps->which");
1220 slepc 73
 
1560 slepc 74
  if (!eps->extraction) {
75
    ierr = EPSSetExtraction(eps,EPS_RITZ);CHKERRQ(ierr);
76
  } else if (eps->extraction!=EPS_RITZ && eps->extraction!=EPS_HARMONIC) {
1574 slepc 77
    SETERRQ(PETSC_ERR_SUP,"Unsupported extraction type");
1426 slepc 78
  }
79
 
1171 slepc 80
  ierr = EPSAllocateSolution(eps);CHKERRQ(ierr);
81
  ierr = PetscFree(eps->T);CHKERRQ(ierr);
1661 slepc 82
  if (!eps->ishermitian || eps->extraction==EPS_HARMONIC) {
83
    ierr = PetscMalloc(eps->ncv*eps->ncv*sizeof(PetscScalar),&eps->T);CHKERRQ(ierr);
1812 antodo 84
    eps->schur_func = EPSGetSchurUpdate_Default;
85
  } else eps->schur_func = EPSGetSchurUpdate_Hermitian;
1755 antodo 86
  ierr = EPSDefaultGetWork(eps,1);CHKERRQ(ierr);
1171 slepc 87
  PetscFunctionReturn(0);
88
}
89
 
90
#undef __FUNCT__  
1476 slepc 91
#define __FUNCT__ "EPSProjectedKSNonsym"
1424 slepc 92
/*
93
   EPSProjectedKSNonsym - Solves the projected eigenproblem in the Krylov-Schur
94
   method (non-symmetric case).
95
 
96
   On input:
97
     l is the number of vectors kept in previous restart (0 means first restart)
98
     S is the projected matrix (leading dimension is lds)
99
 
100
   On output:
101
     S has (real) Schur form with diagonal blocks sorted appropriately
1494 slepc 102
     Q contains the corresponding Schur vectors (order n, leading dimension n)
1424 slepc 103
*/
1509 slepc 104
PetscErrorCode EPSProjectedKSNonsym(EPS eps,PetscInt l,PetscScalar *S,PetscInt lds,PetscScalar *Q,PetscInt n)
1424 slepc 105
{
106
  PetscErrorCode ierr;
1509 slepc 107
  PetscInt       i;
1424 slepc 108
 
109
  PetscFunctionBegin;
1498 slepc 110
  if (l==0) {
1424 slepc 111
    ierr = PetscMemzero(Q,n*n*sizeof(PetscScalar));CHKERRQ(ierr);
112
    for (i=0;i<n;i++)
113
      Q[i*(n+1)] = 1.0;
114
  } else {
115
    /* Reduce S to Hessenberg form, S <- Q S Q' */
116
    ierr = EPSDenseHessenberg(n,eps->nconv,S,lds,Q);CHKERRQ(ierr);
117
  }
118
  /* Reduce S to (quasi-)triangular form, S <- Q S Q' */
119
  ierr = EPSDenseSchur(n,eps->nconv,S,lds,Q,eps->eigr,eps->eigi);CHKERRQ(ierr);
120
  /* Sort the remaining columns of the Schur form */
1823 antodo 121
  ierr = EPSSortDenseSchur(eps,n,eps->nconv,S,lds,Q,eps->eigr,eps->eigi);CHKERRQ(ierr);    
1424 slepc 122
  PetscFunctionReturn(0);
123
}
124
 
125
#undef __FUNCT__  
1171 slepc 126
#define __FUNCT__ "EPSSolve_KRYLOVSCHUR"
127
PetscErrorCode EPSSolve_KRYLOVSCHUR(EPS eps)
128
{
129
  PetscErrorCode ierr;
1474 slepc 130
 
131
  PetscFunctionBegin;
132
  if (eps->ishermitian) {
1661 slepc 133
    switch (eps->extraction) {
134
      case EPS_RITZ:
135
        ierr = EPSSolve_KRYLOVSCHUR_SYMM(eps);CHKERRQ(ierr);
136
        break;
137
      case EPS_HARMONIC:
138
        ierr = EPSSolve_KRYLOVSCHUR_HARMONIC(eps);CHKERRQ(ierr);
139
        break;
140
      default: SETERRQ(PETSC_ERR_SUP,"Unsupported extraction type");
141
    }
1474 slepc 142
  } else {
1560 slepc 143
    switch (eps->extraction) {
1498 slepc 144
      case EPS_RITZ:
145
        ierr = EPSSolve_KRYLOVSCHUR_DEFAULT(eps);CHKERRQ(ierr);
146
        break;
147
      case EPS_HARMONIC:
148
        ierr = EPSSolve_KRYLOVSCHUR_HARMONIC(eps);CHKERRQ(ierr);
149
        break;
1560 slepc 150
      default: SETERRQ(PETSC_ERR_SUP,"Unsupported extraction type");
1498 slepc 151
    }
1474 slepc 152
  }
153
  PetscFunctionReturn(0);
154
}
155
 
156
#undef __FUNCT__  
157
#define __FUNCT__ "EPSSolve_KRYLOVSCHUR_DEFAULT"
158
PetscErrorCode EPSSolve_KRYLOVSCHUR_DEFAULT(EPS eps)
159
{
160
  PetscErrorCode ierr;
1794 antodo 161
  PetscInt       i,k,l,lwork;
1755 antodo 162
  Vec            u=eps->work[0];
1498 slepc 163
  PetscScalar    *S=eps->T,*Q,*work;
164
  PetscReal      beta;
1171 slepc 165
  PetscTruth     breakdown;
166
 
167
  PetscFunctionBegin;
168
  ierr = PetscMemzero(S,eps->ncv*eps->ncv*sizeof(PetscScalar));CHKERRQ(ierr);
1794 antodo 169
  ierr = PetscMalloc(eps->ncv*eps->ncv*sizeof(PetscScalar),&Q);CHKERRQ(ierr); eps->Z = Q;
1171 slepc 170
  lwork = (eps->ncv+4)*eps->ncv;
1474 slepc 171
  ierr = PetscMalloc(lwork*sizeof(PetscScalar),&work);CHKERRQ(ierr);
1171 slepc 172
 
173
  /* Get the starting Arnoldi vector */
174
  ierr = EPSGetStartVector(eps,0,eps->V[0],PETSC_NULL);CHKERRQ(ierr);
1172 slepc 175
  l = 0;
1171 slepc 176
 
177
  /* Restart loop */
178
  while (eps->reason == EPS_CONVERGED_ITERATING) {
1220 slepc 179
    eps->its++;
1171 slepc 180
 
181
    /* Compute an nv-step Arnoldi factorization */
1794 antodo 182
    eps->nv = PetscMin(eps->nconv+eps->mpd,eps->ncv);
183
    ierr = EPSBasicArnoldi(eps,PETSC_FALSE,S,eps->ncv,eps->V,eps->nconv+l,&eps->nv,u,&beta,&breakdown);CHKERRQ(ierr);
1171 slepc 184
    ierr = VecScale(u,1.0/beta);CHKERRQ(ierr);
185
 
1424 slepc 186
    /* Solve projected problem and compute residual norm estimates */
1794 antodo 187
    ierr = EPSProjectedKSNonsym(eps,l,S,eps->ncv,Q,eps->nv);CHKERRQ(ierr);
188
    ierr = ArnoldiResiduals(S,eps->ncv,Q,beta,eps->nconv,eps->nv,eps->eigr,eps->eigi,eps->errest,work);CHKERRQ(ierr);
1171 slepc 189
 
1172 slepc 190
    /* Check convergence */
1794 antodo 191
    ierr = (*eps->conv_func)(eps,eps->nv,eps->nconv,eps->eigr,eps->eigi,eps->errest,eps->conv,eps->conv_ctx);CHKERRQ(ierr);
1172 slepc 192
    k = eps->nconv;
1794 antodo 193
    while (k<eps->nv && eps->conv[k]) k++;
1172 slepc 194
    if (eps->its >= eps->max_it) eps->reason = EPS_DIVERGED_ITS;
195
    if (k >= eps->nev) eps->reason = EPS_CONVERGED_TOL;
196
 
1175 slepc 197
    /* Update l */
1172 slepc 198
    if (eps->reason != EPS_CONVERGED_ITERATING || breakdown) l = 0;
199
    else {
1794 antodo 200
      l = (eps->nv-k)/2;
1172 slepc 201
#if !defined(PETSC_USE_COMPLEX)
1185 slepc 202
      if (S[(k+l-1)*(eps->ncv+1)+1] != 0.0) {
1794 antodo 203
        if (k+l<eps->nv-1) l = l+1;
1468 slepc 204
        else l = l-1;
1172 slepc 205
      }
206
#endif
207
    }
1175 slepc 208
 
1172 slepc 209
    if (eps->reason == EPS_CONVERGED_ITERATING) {
1171 slepc 210
      if (breakdown) {
1474 slepc 211
        /* Start a new Arnoldi factorization */
1468 slepc 212
        PetscInfo2(eps,"Breakdown in Krylov-Schur method (it=%i norm=%g)\n",eps->its,beta);
213
        ierr = EPSGetStartVector(eps,k,eps->V[k],&breakdown);CHKERRQ(ierr);
214
        if (breakdown) {
1172 slepc 215
          eps->reason = EPS_DIVERGED_BREAKDOWN;
1468 slepc 216
          PetscInfo(eps,"Unable to generate more start vectors\n");
217
        }
1172 slepc 218
      } else {
1474 slepc 219
        /* Prepare the Rayleigh quotient for restart */
1468 slepc 220
        for (i=k;i<k+l;i++) {
1794 antodo 221
          S[i*eps->ncv+k+l] = Q[(i+1)*eps->nv-1]*beta;
1468 slepc 222
        }
1171 slepc 223
      }
1175 slepc 224
    }
1467 slepc 225
    /* Update the corresponding vectors V(:,idx) = V*Q(:,idx) */
1794 antodo 226
    ierr = SlepcUpdateVectors(eps->nv,eps->V,eps->nconv,k+l,Q,eps->nv,PETSC_FALSE);CHKERRQ(ierr);
1582 slepc 227
 
1467 slepc 228
    if (eps->reason == EPS_CONVERGED_ITERATING && !breakdown) {
229
      ierr = VecCopy(u,eps->V[k+l]);CHKERRQ(ierr);
230
    }
231
    eps->nconv = k;
232
 
1794 antodo 233
    EPSMonitor(eps,eps->its,eps->nconv,eps->eigr,eps->eigi,eps->errest,eps->nv);
1467 slepc 234
 
1172 slepc 235
  }
1171 slepc 236
 
1794 antodo 237
  ierr = PetscFree(Q);CHKERRQ(ierr); eps->Z = PETSC_NULL;
1474 slepc 238
  ierr = PetscFree(work);CHKERRQ(ierr);
1171 slepc 239
  PetscFunctionReturn(0);
240
}
241
 
242
EXTERN_C_BEGIN
243
#undef __FUNCT__  
244
#define __FUNCT__ "EPSCreate_KRYLOVSCHUR"
245
PetscErrorCode EPSCreate_KRYLOVSCHUR(EPS eps)
246
{
247
  PetscFunctionBegin;
248
  eps->data                      = PETSC_NULL;
249
  eps->ops->solve                = EPSSolve_KRYLOVSCHUR;
250
  eps->ops->solvets              = PETSC_NULL;
251
  eps->ops->setup                = EPSSetUp_KRYLOVSCHUR;
252
  eps->ops->setfromoptions       = PETSC_NULL;
253
  eps->ops->destroy              = EPSDestroy_Default;
254
  eps->ops->view                 = PETSC_NULL;
255
  eps->ops->backtransform        = EPSBackTransform_Default;
256
  eps->ops->computevectors       = EPSComputeVectors_Schur;
257
  PetscFunctionReturn(0);
258
}
259
EXTERN_C_END
260