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
538 dsic.upv.es!jroman 1
/*                      
1707 jroman 2
   Common subroutines for all Krylov-type solvers.
6 dsic.upv.es!jroman 3
 
1376 slepc 4
   - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
1672 slepc 5
   SLEPc - Scalable Library for Eigenvalue Problem Computations
6
   Copyright (c) 2002-2009, Universidad Politecnica de Valencia, Spain
1376 slepc 7
 
1672 slepc 8
   This file is part of SLEPc.
9
 
10
   SLEPc is free software: you can redistribute it and/or modify it under  the
11
   terms of version 3 of the GNU Lesser General Public License as published by
12
   the Free Software Foundation.
13
 
14
   SLEPc  is  distributed in the hope that it will be useful, but WITHOUT  ANY
15
   WARRANTY;  without even the implied warranty of MERCHANTABILITY or  FITNESS
16
   FOR  A  PARTICULAR PURPOSE. See the GNU Lesser General Public  License  for
17
   more details.
18
 
19
   You  should have received a copy of the GNU Lesser General  Public  License
20
   along with SLEPc. If not, see <http://www.gnu.org/licenses/>.
1376 slepc 21
   - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
6 dsic.upv.es!jroman 22
*/
1376 slepc 23
 
1521 slepc 24
#include "private/epsimpl.h"                /*I "slepceps.h" I*/
6 dsic.upv.es!jroman 25
#include "slepcblaslapack.h"
26
 
27
#undef __FUNCT__  
431 dsic.upv.es!antodo 28
#define __FUNCT__ "EPSBasicArnoldi"
538 dsic.upv.es!jroman 29
/*
30
   EPSBasicArnoldi - Computes an m-step Arnoldi factorization. The first k
31
   columns are assumed to be locked and therefore they are not modified. On
32
   exit, the following relation is satisfied:
33
 
34
                    OP * V - V * H = f * e_m^T
35
 
36
   where the columns of V are the Arnoldi vectors (which are B-orthonormal),
591 dsic.upv.es!jroman 37
   H is an upper Hessenberg matrix, f is the residual vector and e_m is
38
   the m-th vector of the canonical basis. The vector f is B-orthogonal to
39
   the columns of V. On exit, beta contains the B-norm of f and the next
40
   Arnoldi vector can be computed as v_{m+1} = f / beta.
538 dsic.upv.es!jroman 41
*/
1574 slepc 42
PetscErrorCode EPSBasicArnoldi(EPS eps,PetscTruth trans,PetscScalar *H,PetscInt ldh,Vec *V,PetscInt k,PetscInt *M,Vec f,PetscReal *beta,PetscTruth *breakdown)
431 dsic.upv.es!antodo 43
{
476 dsic.upv.es!antodo 44
  PetscErrorCode ierr;
1755 antodo 45
  PetscInt       j,m = *M;
476 dsic.upv.es!antodo 46
  PetscReal      norm;
431 dsic.upv.es!antodo 47
 
48
  PetscFunctionBegin;
1538 slepc 49
 
574 dsic.upv.es!antodo 50
  for (j=k;j<m-1;j++) {
879 ono.com!jroman 51
    if (trans) { ierr = STApplyTranspose(eps->OP,V[j],V[j+1]);CHKERRQ(ierr); }
52
    else { ierr = STApply(eps->OP,V[j],V[j+1]);CHKERRQ(ierr); }
1755 antodo 53
    ierr = IPOrthogonalize(eps->ip,eps->nds,eps->DS,j+1,PETSC_NULL,V,V[j+1],H+ldh*j,&norm,breakdown);CHKERRQ(ierr);
1574 slepc 54
    H[j+1+ldh*j] = norm;
1113 slepc 55
    if (*breakdown) {
1049 slepc 56
      *M = j+1;
57
      *beta = norm;
58
      PetscFunctionReturn(0);
828 dsic.upv.es!antodo 59
    } else {
60
      ierr = VecScale(V[j+1],1/norm);CHKERRQ(ierr);
549 dsic.upv.es!antodo 61
    }
431 dsic.upv.es!antodo 62
  }
1600 slepc 63
  if (trans) { ierr = STApplyTranspose(eps->OP,V[m-1],f);CHKERRQ(ierr); }
64
  else { ierr = STApply(eps->OP,V[m-1],f);CHKERRQ(ierr); }
1755 antodo 65
  ierr = IPOrthogonalize(eps->ip,eps->nds,eps->DS,m,PETSC_NULL,V,f,H+ldh*(m-1),beta,PETSC_NULL);CHKERRQ(ierr);
1615 slepc 66
 
431 dsic.upv.es!antodo 67
  PetscFunctionReturn(0);
68
}
69
 
70
#undef __FUNCT__  
879 ono.com!jroman 71
#define __FUNCT__ "ArnoldiResiduals"
72
/*
73
   EPSArnoldiResiduals - Computes the 2-norm of the residual vectors from
74
   the information provided by the m-step Arnoldi factorization,
75
 
76
                    OP * V - V * H = f * e_m^T
77
 
78
   For the approximate eigenpair (k_i,V*y_i), the residual norm is computed as
79
   |beta*y(end,i)| where beta is the norm of f and y is the corresponding
80
   eigenvector of H.
81
*/
1830 antodo 82
PetscErrorCode ArnoldiResiduals(PetscScalar *H,PetscInt ldh_,PetscScalar *U,PetscScalar *Y,PetscReal beta,PetscInt nconv,PetscInt ncv_,PetscScalar *eigr,PetscScalar *eigi,PetscReal *errest,PetscScalar *work)
879 ono.com!jroman 83
{
883 ono.com!jroman 84
#if defined(SLEPC_MISSING_LAPACK_TREVC)
85
  PetscFunctionBegin;
86
  SETERRQ(PETSC_ERR_SUP,"TREVC - Lapack routine is unavailable.");
87
#else
879 ono.com!jroman 88
  PetscErrorCode ierr;
1641 slepc 89
  PetscInt       i;
1862 antodo 90
  PetscBLASInt   mout,info,ldh,ncv,inc = 1;
91
  PetscScalar   tmp;
92
  PetscReal     norm;
879 ono.com!jroman 93
#if defined(PETSC_USE_COMPLEX)
1641 slepc 94
  PetscReal      *rwork=(PetscReal*)(work+3*ncv_);
1862 antodo 95
#else
96
  PetscReal     normi;
879 ono.com!jroman 97
#endif
98
 
99
  PetscFunctionBegin;
1641 slepc 100
  ldh = PetscBLASIntCast(ldh_);
101
  ncv = PetscBLASIntCast(ncv_);
1830 antodo 102
  if (!Y) Y=work+4*ncv_;
879 ono.com!jroman 103
 
104
  /* Compute eigenvectors Y of H */
105
  ierr = PetscMemcpy(Y,U,ncv*ncv*sizeof(PetscScalar));CHKERRQ(ierr);
1339 slepc 106
  ierr = PetscLogEventBegin(EPS_Dense,0,0,0,0);CHKERRQ(ierr);
879 ono.com!jroman 107
#if !defined(PETSC_USE_COMPLEX)
1536 slepc 108
  LAPACKtrevc_("R","B",PETSC_NULL,&ncv,H,&ldh,PETSC_NULL,&ncv,Y,&ncv,&ncv,&mout,work,&info);
879 ono.com!jroman 109
#else
1536 slepc 110
  LAPACKtrevc_("R","B",PETSC_NULL,&ncv,H,&ldh,PETSC_NULL,&ncv,Y,&ncv,&ncv,&mout,work,rwork,&info);
879 ono.com!jroman 111
#endif
1339 slepc 112
  ierr = PetscLogEventEnd(EPS_Dense,0,0,0,0);CHKERRQ(ierr);
879 ono.com!jroman 113
  if (info) SETERRQ1(PETSC_ERR_LIB,"Error in Lapack xTREVC %i",info);
114
 
1862 antodo 115
  /* normalize eigenvectors */
116
  for (i=0;i<ncv;i++) {
117
#if !defined(PETSC_USE_COMPLEX)
118
    if (eigi[i] != 0.0) {
119
      norm = BLASnrm2_(&ncv,Y+i*ncv,&inc);
120
      normi = BLASnrm2_(&ncv,Y+(i+1)*ncv,&inc);
121
      tmp = 1.0 / SlepcAbsEigenvalue(norm,normi);
122
      BLASscal_(&ncv,&tmp,Y+i*ncv,&inc);
123
      BLASscal_(&ncv,&tmp,Y+(i+1)*ncv,&inc);
124
      i++;    
125
    } else
126
#endif
127
    {
128
      norm = BLASnrm2_(&ncv,Y+i*ncv,&inc);
129
      tmp = 1.0 / norm;
130
      BLASscal_(&ncv,&tmp,Y+i*ncv,&inc);
131
    }
132
  }
133
 
879 ono.com!jroman 134
  /* Compute residual norm estimates as beta*abs(Y(m,:)) */
135
  for (i=nconv;i<ncv;i++) {
1791 antodo 136
#if !defined(PETSC_USE_COMPLEX)
137
    if (eigi[i] != 0 && i<ncv-1) {
138
      errest[i] = beta*SlepcAbsEigenvalue(Y[i*ncv+ncv-1],Y[(i+1)*ncv+ncv-1]);
139
      errest[i+1] = errest[i];
140
      i++;
141
    } else
142
#endif
1785 antodo 143
    errest[i] = beta*PetscAbsScalar(Y[i*ncv+ncv-1]);
879 ono.com!jroman 144
  }  
145
  PetscFunctionReturn(0);
883 ono.com!jroman 146
#endif
879 ono.com!jroman 147
}
148
 
149
#undef __FUNCT__  
1958 jroman 150
#define __FUNCT__ "ArnoldiResiduals2"
151
/*
152
   EPSArnoldiResiduals - Estimates the 2-norm of the residual vectors from
153
   the information provided by the m-step Arnoldi factorization,
154
 
155
                    OP * V - V * H = f * e_m^T
156
 
157
   For the approximate eigenpair (k_i,V*y_i), the residual norm is computed as
158
   |beta*y(end,i)| where beta is the norm of f and y is the corresponding
159
   eigenvector of H.
160
 
161
   Input Parameters:
2057 jroman 162
     H - (quasi-)triangular matrix (dimension nv, leading dimension ldh)
163
     U - orthogonal transformation matrix (dimension nv, leading dimension nv)
164
     beta - norm of f
165
     i - which eigenvector to process
166
     iscomplex - true if a complex conjugate pair (in real scalars)
1958 jroman 167
 
168
   Output parameters:
2057 jroman 169
     Y - computed eigenvectors, 2 columns if iscomplex=true (leading dimension nv)
170
     est - computed residual norm estimate
1958 jroman 171
 
2057 jroman 172
   Workspace:
173
     work is workspace to store 3*nv scalars, nv booleans and nv reals
1958 jroman 174
*/
175
PetscErrorCode ArnoldiResiduals2(PetscScalar *H,PetscInt ldh_,PetscScalar *U,PetscScalar *Y,PetscReal beta,PetscInt i,PetscTruth iscomplex,PetscInt nv_,PetscReal *est,PetscScalar *work)
176
{
177
#if defined(SLEPC_MISSING_LAPACK_TREVC)
178
  PetscFunctionBegin;
179
  SETERRQ(PETSC_ERR_SUP,"TREVC - Lapack routine is unavailable.");
180
#else
181
  PetscErrorCode ierr;
182
  PetscInt       k;
183
  PetscBLASInt   mm,mout,info,ldh,nv,inc = 1;
184
  PetscScalar    tmp,done=1.0,zero=0.0;
185
  PetscReal      norm;
186
  PetscTruth     *select=(PetscTruth*)(work+4*nv_);
187
#if defined(PETSC_USE_COMPLEX)
188
  PetscReal      *rwork=(PetscReal*)(work+3*nv_);
189
#endif
190
 
191
  PetscFunctionBegin;
192
  ldh = PetscBLASIntCast(ldh_);
193
  nv = PetscBLASIntCast(nv_);
194
  for (k=0;k<nv;k++) select[k] = PETSC_FALSE;
195
 
196
  /* Compute eigenvectors Y of H */
197
  mm = iscomplex? 2: 1;
198
  select[i] = PETSC_TRUE;
199
#if !defined(PETSC_USE_COMPLEX)
200
  if (iscomplex) select[i+1] = PETSC_TRUE;
201
  LAPACKtrevc_("R","S",select,&nv,H,&ldh,PETSC_NULL,&nv,Y,&nv,&mm,&mout,work,&info);
202
#else
2057 jroman 203
  LAPACKtrevc_("R","S",select,&nv,H,&ldh,PETSC_NULL,&nv,Y,&nv,&mm,&mout,work,rwork,&info);
1958 jroman 204
#endif
205
  if (info) SETERRQ1(PETSC_ERR_LIB,"Error in Lapack xTREVC %i",info);
206
  if (mout != mm) SETERRQ(PETSC_ERR_ARG_WRONG,"Inconsistent arguments");
207
  ierr = PetscMemcpy(work,Y,mout*nv*sizeof(PetscScalar));CHKERRQ(ierr);
208
 
209
  /* accumulate and normalize eigenvectors */
210
  BLASgemv_("N",&nv,&nv,&done,U,&nv,work,&inc,&zero,Y,&inc);
211
#if !defined(PETSC_USE_COMPLEX)
212
  if (iscomplex) BLASgemv_("N",&nv,&nv,&done,U,&nv,work+nv,&inc,&zero,Y+nv,&inc);
213
#endif
214
  mm = mm*nv;
215
  norm = BLASnrm2_(&mm,Y,&inc);
216
  tmp = 1.0 / norm;
217
  BLASscal_(&mm,&tmp,Y,&inc);
218
 
219
  /* Compute residual norm estimate as beta*abs(Y(m,:)) */
220
#if !defined(PETSC_USE_COMPLEX)
221
  if (iscomplex) {
2056 jroman 222
    *est = beta*SlepcAbsEigenvalue(Y[nv-1],Y[2*nv-1]);
1958 jroman 223
  } else
224
#endif
2056 jroman 225
  *est = beta*PetscAbsScalar(Y[nv-1]);
1958 jroman 226
 
227
  PetscFunctionReturn(0);
228
#endif
229
}
230
 
231
#undef __FUNCT__  
2059 jroman 232
#define __FUNCT__ "EPSKrylovConvergence"
233
/*
234
   EPSKrylovConvergence - Implements the loop that checks for convergence
235
   in Krylov methods.
236
 
237
   Input Parameters:
238
     eps   - the eigensolver; some error estimates are updated in eps->errest
239
     issym - whether the projected problem is symmetric or not
240
     kini  - initial value of k (the loop variable)
241
     nits  - number of iterations of the loop
242
     S     - Schur form of projected matrix (not referenced if issym)
243
     lds   - leading dimension of S
244
     Q     - Schur vectors of projected matrix (eigenvectors if issym)
245
     V     - set of basis vectors (used only if trueresidual is activated)
246
     nv    - number of vectors to process (dimension of Q, columns of V)
247
     beta  - norm of f (the residual vector of the Arnoldi/Lanczos factorization)
248
     corrf - correction factor for residual estimates (only in harmonic KS)
249
 
250
   Output Parameters:
251
     kout  - the first index where the convergence test failed
252
 
253
   Workspace:
254
     work is workspace to store 5*nv scalars, nv booleans and nv reals (only if !issym)
255
*/
256
PetscErrorCode EPSKrylovConvergence(EPS eps,PetscTruth issym,PetscInt kini,PetscInt nits,PetscScalar *S,PetscInt lds,PetscScalar *Q,Vec *V,PetscInt nv,PetscReal beta,PetscReal corrf,PetscInt *kout,PetscScalar *work)
257
{
258
  PetscErrorCode ierr;
259
  PetscInt       k,marker;
260
  PetscScalar    re,im,*Z,*work2;
261
  PetscReal      resnorm;
262
  PetscTruth     iscomplex,conv,isshift;
263
 
264
  PetscFunctionBegin;
265
  if (!issym) { Z = work; work2 = work+2*nv; }
266
  ierr = PetscTypeCompare((PetscObject)eps->OP,STSHIFT,&isshift);CHKERRQ(ierr);
267
  marker = -1;
268
  for (k=kini;k<kini+nits;k++) {
269
    /* eigenvalue */
270
    re = eps->eigr[k];
271
    im = eps->eigi[k];
272
    if (eps->trueres || isshift) {
273
      ierr = STBackTransform(eps->OP,1,&re,&im);CHKERRQ(ierr);
274
    }
275
    iscomplex = PETSC_FALSE;
276
    if (!issym && k<nv-1 && S[k+1+k*lds] != 0.0) iscomplex = PETSC_TRUE;
277
    /* residual norm */
278
    if (issym) {
279
      resnorm = beta*PetscAbsScalar(Q[(k-kini+1)*nv-1]);
280
    } else {
281
      ierr = ArnoldiResiduals2(S,lds,Q,Z,beta,k,iscomplex,nv,&resnorm,work2);CHKERRQ(ierr);
282
    }
283
    if (eps->trueres) {
284
      if (issym) Z = Q+(k-kini)*nv;
285
      ierr = EPSComputeTrueResidual(eps,re,im,Z,V,nv,&resnorm);CHKERRQ(ierr);
286
    }
287
    else resnorm *= corrf;
288
    /* error estimate */
289
    eps->errest[k] = resnorm;
290
    ierr = (*eps->conv_func)(eps,re,im,&eps->errest[k],&conv,eps->conv_ctx);CHKERRQ(ierr);
291
    if (marker==-1 && !conv) marker = k;
292
    if (iscomplex) { eps->errest[k+1] = eps->errest[k]; k++; }
293
    if (marker!=-1 && !eps->trackall) break;
294
  }
295
  if (marker!=-1) k = marker;
296
  *kout = k;
297
 
298
  PetscFunctionReturn(0);
299
}
300
 
301
#undef __FUNCT__  
1707 jroman 302
#define __FUNCT__ "EPSFullLanczos"
1484 slepc 303
/*
1707 jroman 304
   EPSFullLanczos - Computes an m-step Lanczos factorization with full
305
   reorthogonalization.  At each Lanczos step, the corresponding Lanczos
306
   vector is orthogonalized with respect to all previous Lanczos vectors.
307
   This is equivalent to computing an m-step Arnoldi factorization and
308
   exploting symmetry of the operator.
1484 slepc 309
 
1707 jroman 310
   The first k columns are assumed to be locked and therefore they are
311
   not modified. On exit, the following relation is satisfied:
1484 slepc 312
 
1707 jroman 313
                    OP * V - V * T = f * e_m^T
1484 slepc 314
 
1707 jroman 315
   where the columns of V are the Lanczos vectors (which are B-orthonormal),
316
   T is a real symmetric tridiagonal matrix, f is the residual vector and e_m
317
   is the m-th vector of the canonical basis. The tridiagonal is stored as
318
   two arrays: alpha contains the diagonal elements, beta the off-diagonal.
319
   The vector f is B-orthogonal to the columns of V. On exit, the last element
320
   of beta contains the B-norm of f and the next Lanczos vector can be
321
   computed as v_{m+1} = f / beta(end).
1484 slepc 322
 
323
*/
1707 jroman 324
PetscErrorCode EPSFullLanczos(EPS eps,PetscReal *alpha,PetscReal *beta,Vec *V,PetscInt k,PetscInt *M,Vec f,PetscTruth *breakdown)
1484 slepc 325
{
326
  PetscErrorCode ierr;
1707 jroman 327
  PetscInt       j,m = *M;
328
  PetscReal      norm;
1755 antodo 329
  PetscScalar    *hwork,lhwork[100];
1484 slepc 330
 
331
  PetscFunctionBegin;
1755 antodo 332
  if (m > 100) {
1707 jroman 333
    ierr = PetscMalloc((eps->nds+m)*sizeof(PetscScalar),&hwork);CHKERRQ(ierr);
334
  } else {
335
    hwork = lhwork;
1484 slepc 336
  }
337
 
1707 jroman 338
  for (j=k;j<m-1;j++) {
339
    ierr = STApply(eps->OP,V[j],V[j+1]);CHKERRQ(ierr);
1755 antodo 340
    ierr = IPOrthogonalize(eps->ip,eps->nds,eps->DS,j+1,PETSC_NULL,V,V[j+1],hwork,&norm,breakdown);CHKERRQ(ierr);
341
    alpha[j-k] = PetscRealPart(hwork[j]);
1707 jroman 342
    beta[j-k] = norm;
343
    if (*breakdown) {
344
      *M = j+1;
1755 antodo 345
      if (m > 100) {
1707 jroman 346
        ierr = PetscFree(hwork);CHKERRQ(ierr);
347
      }
348
      PetscFunctionReturn(0);
1083 slepc 349
    } else {
1707 jroman 350
      ierr = VecScale(V[j+1],1.0/norm);CHKERRQ(ierr);
1083 slepc 351
    }
431 dsic.upv.es!antodo 352
  }
1707 jroman 353
  ierr = STApply(eps->OP,V[m-1],f);CHKERRQ(ierr);
1755 antodo 354
  ierr = IPOrthogonalize(eps->ip,eps->nds,eps->DS,m,PETSC_NULL,V,f,hwork,&norm,PETSC_NULL);CHKERRQ(ierr);
355
  alpha[m-1-k] = PetscRealPart(hwork[m-1]);
1707 jroman 356
  beta[m-1-k] = norm;
431 dsic.upv.es!antodo 357
 
1755 antodo 358
  if (m > 100) {
1707 jroman 359
    ierr = PetscFree(hwork);CHKERRQ(ierr);
1484 slepc 360
  }
431 dsic.upv.es!antodo 361
  PetscFunctionReturn(0);
362
}
363
 
1083 slepc 364