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
1878 antodo 1
/*                      
2
 
3
   SLEPc eigensolver: "dsitrlanczos"
4
 
5
   Method: Thick restart Lanczos with full reorthogonalization and dynamic shift and invert
6
 
7
   Last update: Jan 2010
8
 
9
   - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
10
   SLEPc - Scalable Library for Eigenvalue Problem Computations
2116 eromero 11
   Copyright (c) 2002-2010, Universidad Politecnica de Valencia, Spain
1878 antodo 12
 
13
   This file is part of SLEPc.
14
 
15
   SLEPc is free software: you can redistribute it and/or modify it under  the
16
   terms of version 3 of the GNU Lesser General Public License as published by
17
   the Free Software Foundation.
18
 
19
   SLEPc  is  distributed in the hope that it will be useful, but WITHOUT  ANY
20
   WARRANTY;  without even the implied warranty of MERCHANTABILITY or  FITNESS
21
   FOR  A  PARTICULAR PURPOSE. See the GNU Lesser General Public  License  for
22
   more details.
23
 
24
   You  should have received a copy of the GNU Lesser General  Public  License
25
   along with SLEPc. If not, see <http://www.gnu.org/licenses/>.
26
   - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
27
*/
28
 
29
#include "private/epsimpl.h"                /*I "slepceps.h" I*/
30
#include "slepcblaslapack.h"
31
 
1947 jroman 32
PetscErrorCode EPSSolve_DSITRLANCZOS(EPS);
33
 
1878 antodo 34
extern PetscErrorCode EPSProjectedKSSym(EPS eps,PetscInt n,PetscInt l,PetscReal *a,PetscReal *b,PetscScalar *eig,PetscScalar *Q,PetscReal *work,PetscInt *perm);
35
 
36
#undef __FUNCT__  
37
#define __FUNCT__ "EPSSetUp_DSITRLANCZOS"
38
PetscErrorCode EPSSetUp_DSITRLANCZOS(EPS eps)
39
{
40
  PetscErrorCode ierr;
41
  PetscTruth     isSinv;
42
 
43
  PetscFunctionBegin;
44
  if (eps->ncv) { /* ncv set */
45
    if (eps->ncv<eps->nev) SETERRQ(1,"The value of ncv must be at least nev");
46
  }
47
  else if (eps->mpd) { /* mpd set */
1928 jroman 48
    eps->ncv = PetscMin(eps->n,eps->nev+eps->mpd);
1878 antodo 49
  }
50
  else { /* neither set: defaults depend on nev being small or large */
1928 jroman 51
    if (eps->nev<500) eps->ncv = PetscMin(eps->n,PetscMax(2*eps->nev,eps->nev+15));
52
    else { eps->mpd = 500; eps->ncv = PetscMin(eps->n,eps->nev+eps->mpd); }
1878 antodo 53
  }
54
  if (!eps->mpd) eps->mpd = eps->ncv;
55
  if (eps->ncv>eps->nev+eps->mpd) SETERRQ(1,"The value of ncv must not be larger than nev+mpd");
1928 jroman 56
  if (!eps->max_it) eps->max_it = PetscMax(100,2*eps->n/eps->ncv);
1878 antodo 57
 
58
  if (!eps->ishermitian)
59
    SETERRQ(PETSC_ERR_SUP,"Requested method is only available for Hermitian problems");
1942 jroman 60
  if (!eps->which) eps->which = EPS_LARGEST_MAGNITUDE;
1878 antodo 61
  if (eps->which==EPS_LARGEST_IMAGINARY || eps->which==EPS_SMALLEST_IMAGINARY)
62
    SETERRQ(1,"Wrong value of eps->which");
63
 
64
  if (!eps->extraction) {
65
    ierr = EPSSetExtraction(eps,EPS_RITZ);CHKERRQ(ierr);
66
  } if (eps->extraction != EPS_RITZ) {
67
    SETERRQ(PETSC_ERR_SUP,"Unsupported extraction type");
68
  }
69
 
2092 jroman 70
  ierr = PetscTypeCompare((PetscObject)eps->OP,STSINVERT,&isSinv);CHKERRQ(ierr);
1878 antodo 71
  if (!isSinv) {
72
    SETERRQ(PETSC_ERR_SUP,"Shift-and-invert ST is needed");
73
  }
74
 
75
  ierr = EPSAllocateSolution(eps);CHKERRQ(ierr);
76
  ierr = EPSDefaultGetWork(eps,1);CHKERRQ(ierr);
1947 jroman 77
 
78
  /* dispatch solve method */
79
  if (eps->leftvecs) SETERRQ(PETSC_ERR_SUP,"Left vectors not supported in this solver");
80
  eps->ops->solve = EPSSolve_DSITRLANCZOS;
1878 antodo 81
  PetscFunctionReturn(0);
82
}
83
 
84
#undef __FUNCT__  
85
#define __FUNCT__ "EPSSolve_DSITRLANCZOS"
86
PetscErrorCode EPSSolve_DSITRLANCZOS(EPS eps)
87
{
88
  PetscErrorCode ierr;
89
  PetscInt       i,k,l,lds,lt,nv,m;
90
  Vec            u=eps->work[0];
91
  PetscScalar    *Q, sigma, lambda, zero = 0.0;
92
  PetscReal      *a,*b,*work,beta,distance = 1e-3;
93
  PetscInt       *iwork;
94
  PetscTruth     breakdown;
95
 
96
  PetscFunctionBegin;
97
  ierr = PetscOptionsGetReal(PETSC_NULL,"-eps_distance",&distance,PETSC_NULL);CHKERRQ(ierr);
98
  lds = PetscMin(eps->mpd,eps->ncv);
99
  ierr = PetscMalloc(lds*lds*sizeof(PetscReal),&work);CHKERRQ(ierr);
2062 jroman 100
  ierr = PetscMalloc(lds*lds*sizeof(PetscScalar),&Q);CHKERRQ(ierr);
1878 antodo 101
  ierr = PetscMalloc(2*lds*sizeof(PetscInt),&iwork);CHKERRQ(ierr);
102
  lt = PetscMin(eps->nev+eps->mpd,eps->ncv);
103
  ierr = PetscMalloc(lt*sizeof(PetscReal),&a);CHKERRQ(ierr);  
104
  ierr = PetscMalloc(lt*sizeof(PetscReal),&b);CHKERRQ(ierr);  
105
 
106
  /* Get the starting Lanczos vector */
107
  ierr = EPSGetStartVector(eps,0,eps->V[0],PETSC_NULL);CHKERRQ(ierr);
108
  l = 0;
109
 
110
  /* Restart loop */
111
  while (eps->reason == EPS_CONVERGED_ITERATING) {
112
    eps->its++;
113
 
114
    /* Compute an nv-step Lanczos factorization */
115
    m = PetscMin(eps->nconv+eps->mpd,eps->ncv);
116
    ierr = EPSFullLanczos(eps,a+l,b+l,eps->V,eps->nconv+l,&m,u,&breakdown);CHKERRQ(ierr);
117
    nv = m - eps->nconv;
118
    beta = b[nv-1];
119
 
120
    /* Solve projected problem and compute residual norm estimates */
121
    ierr = EPSProjectedKSSym(eps,nv,l,a,b,eps->eigr+eps->nconv,Q,work,iwork);CHKERRQ(ierr);
122
 
123
    /* Check convergence */
2062 jroman 124
    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);
1878 antodo 125
    if (eps->its >= eps->max_it) eps->reason = EPS_DIVERGED_ITS;
126
    if (k >= eps->nev) eps->reason = EPS_CONVERGED_TOL;
127
 
128
    /* Transform converged eigenvalues to the original problem */
129
    ierr = STBackTransform(eps->OP,k-eps->nconv,eps->eigr+eps->nconv,eps->eigi+eps->nconv);CHKERRQ(ierr);
130
 
131
    /* Update l */
132
    if (eps->reason != EPS_CONVERGED_ITERATING || breakdown) l = 0;
133
    else {
134
      l = (eps->nconv+nv-k)/2;
135
      /* Update shift */
136
      ierr = STGetShift(eps->OP,&sigma);CHKERRQ(ierr);
137
      lambda = eps->eigr[k+1];
138
      ierr = STBackTransform(eps->OP,1,&lambda,&zero);CHKERRQ(ierr);
139
      if (PetscAbsScalar(lambda - sigma)/PetscAbsScalar(sigma) > distance) {
140
        ierr = PetscInfo2(eps,"Shift update its=%i sigma=%g\n",eps->its,lambda);
141
        PetscPushErrorHandler(PetscReturnErrorHandler,PETSC_NULL);
142
        ierr = STSetShift(eps->OP,lambda);
143
        PetscPopErrorHandler();
144
        switch (ierr) {
145
        case PETSC_ERR_MAT_LU_ZRPVT:
146
        case PETSC_ERR_MAT_CH_ZRPVT:
147
          ierr = PetscInfo2(eps,"Factorization error in shift update its=%i sigma=%g\n",eps->its,lambda);
148
          ierr = STSetShift(eps->OP,sigma);CHKERRQ(ierr);
149
          break;
150
        default:
151
          CHKERRQ(ierr);
152
          l = 0; /* do not use restart vectors */
153
        }
154
      }
155
    }
156
 
157
    if (eps->reason == EPS_CONVERGED_ITERATING) {
158
      if (breakdown) {
159
        /* Start a new Lanczos factorization */
160
        PetscInfo2(eps,"Breakdown in TR Lanczos method (it=%i norm=%g)\n",eps->its,beta);
161
        ierr = EPSGetStartVector(eps,k,eps->V[k],&breakdown);CHKERRQ(ierr);
162
        if (breakdown) {
163
          eps->reason = EPS_DIVERGED_BREAKDOWN;
164
          PetscInfo(eps,"Unable to generate more start vectors\n");
165
        }
166
      } else {
167
        /* Prepare the Rayleigh quotient for restart */
168
        for (i=0;i<l;i++) {
169
          a[i] = PetscRealPart(eps->eigr[i+k]);
170
          b[i] = PetscRealPart(Q[nv-1+(i+k-eps->nconv)*nv]*beta);
171
        }
172
      }
173
    }
174
    /* Update the corresponding vectors V(:,idx) = V*Q(:,idx) */
175
    ierr = SlepcUpdateVectors(nv,eps->V+eps->nconv,0,k+l-eps->nconv,Q,nv,PETSC_FALSE);CHKERRQ(ierr);
176
    /* Normalize u and append it to V */
177
    if (eps->reason == EPS_CONVERGED_ITERATING && !breakdown) {
178
      ierr = VecAXPBY(eps->V[k+l],1.0/beta,0.0,u);CHKERRQ(ierr);
179
    }
180
 
181
    EPSMonitor(eps,eps->its,k,eps->eigr,eps->eigi,eps->errest,nv+eps->nconv);
182
    eps->nconv = k;
183
 
184
  }
185
 
2062 jroman 186
  ierr = PetscFree(Q);CHKERRQ(ierr);
1878 antodo 187
  ierr = PetscFree(a);CHKERRQ(ierr);
188
  ierr = PetscFree(b);CHKERRQ(ierr);
189
  ierr = PetscFree(work);CHKERRQ(ierr);
190
  ierr = PetscFree(iwork);CHKERRQ(ierr);
191
  PetscFunctionReturn(0);
192
}
193
 
194
EXTERN_C_BEGIN
195
#undef __FUNCT__  
196
#define __FUNCT__ "EPSCreate_DSITRLANCZOS"
197
PetscErrorCode EPSCreate_DSITRLANCZOS(EPS eps)
198
{
199
  PetscFunctionBegin;
200
  eps->data                      = PETSC_NULL;
201
  eps->ops->setup                = EPSSetUp_DSITRLANCZOS;
202
  eps->ops->setfromoptions       = PETSC_NULL;
203
  eps->ops->destroy              = EPSDestroy_Default;
204
  eps->ops->view                 = PETSC_NULL;
205
  eps->ops->computevectors       = EPSComputeVectors_Default;
206
  PetscFunctionReturn(0);
207
}
208
EXTERN_C_END
209