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
521 dsic.upv.es!antodo 1
/*
545 dsic.upv.es!jroman 2
     This file contains some simple default routines for common operations.  
1376 slepc 3
 
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
   - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
545 dsic.upv.es!jroman 22
*/
1376 slepc 23
 
1521 slepc 24
#include "private/epsimpl.h"   /*I "slepceps.h" I*/
521 dsic.upv.es!antodo 25
#include "slepcblaslapack.h"
26
 
27
#undef __FUNCT__  
28
#define __FUNCT__ "EPSDestroy_Default"
29
PetscErrorCode EPSDestroy_Default(EPS eps)
30
{
31
  PetscErrorCode ierr;
32
 
33
  PetscFunctionBegin;
34
  PetscValidHeaderSpecific(eps,EPS_COOKIE,1);
1040 slepc 35
  ierr = PetscFree(eps->data);CHKERRQ(ierr);
521 dsic.upv.es!antodo 36
 
37
  /* free work vectors */
38
  ierr = EPSDefaultFreeWork(eps);CHKERRQ(ierr);
39
  ierr = EPSFreeSolution(eps);CHKERRQ(ierr);
40
  PetscFunctionReturn(0);
41
}
42
 
43
#undef __FUNCT__  
44
#define __FUNCT__ "EPSBackTransform_Default"
45
PetscErrorCode EPSBackTransform_Default(EPS eps)
46
{
47
  PetscErrorCode ierr;
48
 
49
  PetscFunctionBegin;
50
  PetscValidHeaderSpecific(eps,EPS_COOKIE,1);
1778 antodo 51
  ierr = STBackTransform(eps->OP,eps->nconv,eps->eigr,eps->eigi);CHKERRQ(ierr);
521 dsic.upv.es!antodo 52
  PetscFunctionReturn(0);
53
}
54
 
55
#undef __FUNCT__  
56
#define __FUNCT__ "EPSComputeVectors_Default"
545 dsic.upv.es!jroman 57
/*
58
  EPSComputeVectors_Default - Compute eigenvectors from the vectors
59
  provided by the eigensolver. This version just copies the vectors
60
  and is intended for solvers such as power that provide the eigenvector.
61
 */
521 dsic.upv.es!antodo 62
PetscErrorCode EPSComputeVectors_Default(EPS eps)
63
{
64
  PetscFunctionBegin;
65
  eps->evecsavailable = PETSC_TRUE;
66
  PetscFunctionReturn(0);
67
}
68
 
69
#undef __FUNCT__  
1243 slepc 70
#define __FUNCT__ "EPSComputeVectors_Hermitian"
71
/*
72
  EPSComputeVectors_Hermitian - Copies the Lanczos vectors as eigenvectors
73
  using purification for generalized eigenproblems.
74
 */
75
PetscErrorCode EPSComputeVectors_Hermitian(EPS eps)
76
{
77
  PetscErrorCode ierr;
1509 slepc 78
  PetscInt       i;
1243 slepc 79
  PetscReal      norm;
1582 slepc 80
  Vec            w;
1243 slepc 81
 
82
  PetscFunctionBegin;
1582 slepc 83
  if (eps->isgeneralized) {
84
    /* Purify eigenvectors */
85
    ierr = VecDuplicate(eps->V[0],&w);CHKERRQ(ierr);
86
    for (i=0;i<eps->nconv;i++) {
87
      ierr = VecCopy(eps->V[i],w);CHKERRQ(ierr);
88
      ierr = STApply(eps->OP,w,eps->V[i]);CHKERRQ(ierr);
1765 antodo 89
      ierr = IPNorm(eps->ip,eps->V[i],&norm);CHKERRQ(ierr);
90
      ierr = VecScale(eps->V[i],1.0/norm);CHKERRQ(ierr);
1243 slepc 91
    }
1582 slepc 92
    ierr = VecDestroy(w);CHKERRQ(ierr);
93
  }
1243 slepc 94
  eps->evecsavailable = PETSC_TRUE;
95
  PetscFunctionReturn(0);
96
}
97
 
98
#undef __FUNCT__  
521 dsic.upv.es!antodo 99
#define __FUNCT__ "EPSComputeVectors_Schur"
545 dsic.upv.es!jroman 100
/*
101
  EPSComputeVectors_Schur - Compute eigenvectors from the vectors
102
  provided by the eigensolver. This version is intended for solvers
103
  that provide Schur vectors. Given the partial Schur decomposition
104
  OP*V=V*T, the following steps are performed:
780 dsic.upv.es!jroman 105
      1) compute eigenvectors of T: T*Z=Z*D
106
      2) compute eigenvectors of OP: X=V*Z
107
  If left eigenvectors are required then also do Z'*Tl=D*Z', Y=W*Z
545 dsic.upv.es!jroman 108
 */
521 dsic.upv.es!antodo 109
PetscErrorCode EPSComputeVectors_Schur(EPS eps)
110
{
806 dsic.upv.es!antodo 111
#if defined(SLEPC_MISSING_LAPACK_TREVC)
112
  SETERRQ(PETSC_ERR_SUP,"TREVC - Lapack routine is unavailable.");
113
#else
521 dsic.upv.es!antodo 114
  PetscErrorCode ierr;
1509 slepc 115
  PetscInt       i;
1635 slepc 116
  PetscBLASInt   ncv,nconv,mout,info;
780 dsic.upv.es!jroman 117
  PetscScalar    *Z,*work;
521 dsic.upv.es!antodo 118
#if defined(PETSC_USE_COMPLEX)
119
  PetscReal      *rwork;
120
#endif
1243 slepc 121
  PetscReal      norm;
122
  Vec            w;
521 dsic.upv.es!antodo 123
 
124
  PetscFunctionBegin;
1635 slepc 125
  ncv = PetscBLASIntCast(eps->ncv);
126
  nconv = PetscBLASIntCast(eps->nconv);
521 dsic.upv.es!antodo 127
  if (eps->ishermitian) {
1243 slepc 128
    ierr = EPSComputeVectors_Hermitian(eps);CHKERRQ(ierr);
521 dsic.upv.es!antodo 129
    PetscFunctionReturn(0);
130
  }
1358 slepc 131
  if (eps->ispositive) {
1243 slepc 132
    ierr = VecDuplicate(eps->V[0],&w);CHKERRQ(ierr);
133
  }
521 dsic.upv.es!antodo 134
 
1587 slepc 135
  ierr = PetscMalloc(nconv*nconv*sizeof(PetscScalar),&Z);CHKERRQ(ierr);
136
  ierr = PetscMalloc(3*nconv*sizeof(PetscScalar),&work);CHKERRQ(ierr);
521 dsic.upv.es!antodo 137
#if defined(PETSC_USE_COMPLEX)
1587 slepc 138
  ierr = PetscMalloc(nconv*sizeof(PetscReal),&rwork);CHKERRQ(ierr);
521 dsic.upv.es!antodo 139
#endif
140
 
780 dsic.upv.es!jroman 141
  /* right eigenvectors */
521 dsic.upv.es!antodo 142
#if !defined(PETSC_USE_COMPLEX)
1587 slepc 143
  LAPACKtrevc_("R","A",PETSC_NULL,&nconv,eps->T,&ncv,PETSC_NULL,&nconv,Z,&nconv,&nconv,&mout,work,&info);
521 dsic.upv.es!antodo 144
#else
1587 slepc 145
  LAPACKtrevc_("R","A",PETSC_NULL,&nconv,eps->T,&ncv,PETSC_NULL,&nconv,Z,&nconv,&nconv,&mout,work,rwork,&info);
521 dsic.upv.es!antodo 146
#endif
147
  if (info) SETERRQ1(PETSC_ERR_LIB,"Error in Lapack xTREVC %i",info);
148
 
870 dsic.upv.es!antodo 149
  /* AV = V * Z */
1601 slepc 150
  ierr = SlepcUpdateVectors(eps->nconv,eps->V,0,eps->nconv,Z,eps->nconv,PETSC_FALSE);CHKERRQ(ierr);
1582 slepc 151
  if (eps->ispositive) {
152
    /* Purify eigenvectors */
153
    for (i=0;i<eps->nconv;i++) {
154
      ierr = VecCopy(eps->V[i],w);CHKERRQ(ierr);
155
      ierr = STApply(eps->OP,w,eps->V[i]);CHKERRQ(ierr);
1769 antodo 156
      ierr = VecNormalize(eps->V[i],&norm);CHKERRQ(ierr);
1243 slepc 157
    }
1582 slepc 158
  }
521 dsic.upv.es!antodo 159
 
780 dsic.upv.es!jroman 160
  /* left eigenvectors */
161
  if (eps->solverclass == EPS_TWO_SIDE) {
162
#if !defined(PETSC_USE_COMPLEX)
1587 slepc 163
    LAPACKtrevc_("R","A",PETSC_NULL,&nconv,eps->Tl,&ncv,PETSC_NULL,&nconv,Z,&nconv,&nconv,&mout,work,&info);
780 dsic.upv.es!jroman 164
#else
1587 slepc 165
    LAPACKtrevc_("R","A",PETSC_NULL,&nconv,eps->Tl,&ncv,PETSC_NULL,&nconv,Z,&nconv,&nconv,&mout,work,rwork,&info);
780 dsic.upv.es!jroman 166
#endif
167
    if (info) SETERRQ1(PETSC_ERR_LIB,"Error in Lapack xTREVC %i",info);
168
 
870 dsic.upv.es!antodo 169
    /* AW = W * Z */
1607 slepc 170
    ierr = SlepcUpdateVectors(eps->nconv,eps->W,0,eps->nconv,Z,eps->nconv,PETSC_FALSE);CHKERRQ(ierr);
780 dsic.upv.es!jroman 171
  }
172
 
1804 jroman 173
  /* Fix eigenvectors if balancing was used */
174
  if (eps->balance!=EPSBALANCE_NONE && eps->D) {
175
    for (i=0;i<eps->nconv;i++) {
176
      ierr = VecPointwiseDivide(eps->V[i],eps->V[i],eps->D);CHKERRQ(ierr);
177
      ierr = VecNormalize(eps->V[i],&norm);CHKERRQ(ierr);
178
    }
179
  }
180
 
780 dsic.upv.es!jroman 181
  ierr = PetscFree(Z);CHKERRQ(ierr);
521 dsic.upv.es!antodo 182
  ierr = PetscFree(work);CHKERRQ(ierr);
183
#if defined(PETSC_USE_COMPLEX)
184
  ierr = PetscFree(rwork);CHKERRQ(ierr);
185
#endif
1358 slepc 186
  if (eps->ispositive) {
1243 slepc 187
    ierr = VecDestroy(w);CHKERRQ(ierr);
188
  }
521 dsic.upv.es!antodo 189
  eps->evecsavailable = PETSC_TRUE;
190
  PetscFunctionReturn(0);
806 dsic.upv.es!antodo 191
#endif
521 dsic.upv.es!antodo 192
}
533 dsic.upv.es!antodo 193
 
194
#undef __FUNCT__  
195
#define __FUNCT__ "EPSDefaultGetWork"
196
/*
197
  EPSDefaultGetWork - Gets a number of work vectors.
198
 
199
  Input Parameters:
200
+ eps  - eigensolver context
201
- nw   - number of work vectors to allocate
202
 
203
  Notes:
204
  Call this only if no work vectors have been allocated.
205
 
206
 */
1509 slepc 207
PetscErrorCode EPSDefaultGetWork(EPS eps, PetscInt nw)
533 dsic.upv.es!antodo 208
{
209
  PetscErrorCode ierr;
210
 
211
  PetscFunctionBegin;
212
 
213
  if (eps->nwork != nw) {
214
    if (eps->nwork > 0) {
215
      ierr = VecDestroyVecs(eps->work,eps->nwork); CHKERRQ(ierr);
216
    }
217
    eps->nwork = nw;
1385 slepc 218
    ierr = VecDuplicateVecs(eps->vec_initial,nw,&eps->work); CHKERRQ(ierr);
790 dsic.upv.es!antodo 219
    ierr = PetscLogObjectParents(eps,nw,eps->work);
533 dsic.upv.es!antodo 220
  }
221
 
222
  PetscFunctionReturn(0);
223
}
224
 
225
#undef __FUNCT__  
226
#define __FUNCT__ "EPSDefaultFreeWork"
227
/*
228
  EPSDefaultFreeWork - Free work vectors.
229
 
230
  Input Parameters:
231
. eps  - eigensolver context
232
 
233
 */
234
PetscErrorCode EPSDefaultFreeWork(EPS eps)
235
{
236
  PetscErrorCode ierr;
237
 
238
  PetscFunctionBegin;
239
  PetscValidHeaderSpecific(eps,EPS_COOKIE,1);
240
  if (eps->work)  {
241
    ierr = VecDestroyVecs(eps->work,eps->nwork); CHKERRQ(ierr);
242
  }
243
  PetscFunctionReturn(0);
244
}
1785 antodo 245
 
246
#undef __FUNCT__  
247
#define __FUNCT__ "EPSDefaultConverged"
1794 antodo 248
/*
249
  EPSDefaultConverged - Checks convergence with the relative error estimate.
250
*/
1785 antodo 251
PetscErrorCode EPSDefaultConverged(EPS eps,PetscInt n,PetscInt k,PetscScalar* eigr,PetscScalar* eigi,PetscReal* errest,PetscTruth *conv,void *ctx)
252
{
253
  PetscInt  i;
1794 antodo 254
  PetscReal w;
1785 antodo 255
 
256
  PetscFunctionBegin;
257
  for (i=k; i<n; i++) {
258
    w = SlepcAbsEigenvalue(eigr[i],eigi[i]);
1794 antodo 259
    if (w > errest[i]) errest[i] = errest[i] / w;
260
    if (errest[i] < eps->tol) conv[i] = PETSC_TRUE;
1785 antodo 261
    else conv[i] = PETSC_FALSE;
262
  }
263
  PetscFunctionReturn(0);
264
}
265
 
266
#undef __FUNCT__  
267
#define __FUNCT__ "EPSAbsoluteConverged"
1794 antodo 268
/*
269
  EPSAbsoluteConverged - Checks convergence with the absolute error estimate.
270
*/
1785 antodo 271
PetscErrorCode EPSAbsoluteConverged(EPS eps,PetscInt n,PetscInt k,PetscScalar* eigr,PetscScalar* eigi,PetscReal* errest,PetscTruth *conv,void *ctx)
272
{
273
  PetscInt  i;
274
 
275
  PetscFunctionBegin;
276
  for (i=k; i<n; i++) {
277
    if (errest[i] < eps->tol) conv[i] = PETSC_TRUE;
278
    else conv[i] = PETSC_FALSE;
1794 antodo 279
  }
280
  PetscFunctionReturn(0);
281
}
282
 
283
#undef __FUNCT__  
284
#define __FUNCT__ "EPSResidualConverged"
285
/*
286
  EPSResidualConverged - Checks convergence with the true relative residual for
287
  each eigenpair whose error estimate is lower than the tolerance.
288
*/
289
PetscErrorCode EPSResidualConverged(EPS eps,PetscInt n,PetscInt k,PetscScalar* eigr,PetscScalar* eigi,PetscReal* errest,PetscTruth *conv,void *ctx)
290
{
291
  PetscErrorCode ierr;
292
  Mat            A,B;
293
  Vec            x,y,z;
294
  PetscInt       i;
295
  PetscScalar    re,im;
296
 
297
  PetscFunctionBegin;
298
  ierr = STGetOperators(eps->OP,&A,&B);CHKERRQ(ierr);
299
  ierr = VecDuplicate(eps->V[0],&x);CHKERRQ(ierr);
300
  ierr = VecDuplicate(eps->V[0],&y);CHKERRQ(ierr);
301
  if (B) { ierr = VecDuplicate(eps->V[0],&z);CHKERRQ(ierr); }
302
  for (i=k; i<n; i++) {
303
    if (errest[i] < eps->tol && eps->schur_func) {
304
      if (eps->ishermitian) {
305
        /* compute eigenvalue */
306
        re = eigr[i]; im = 0.0;
307
        ierr = STBackTransform(eps->OP,1,&re,&im);CHKERRQ(ierr);
308
        /* compute schur vector */
309
        ierr = (*eps->schur_func)(eps,i,x);CHKERRQ(ierr);
310
        /* compute residual */
311
        if (B) {
312
          /* purify eigenvector for generalized problem */
313
          ierr = STApply(eps->OP,x,z);CHKERRQ(ierr);
314
          ierr = VecNormalize(z,PETSC_NULL);CHKERRQ(ierr);
315
          ierr = MatMult(A,z,y);CHKERRQ(ierr);
316
          ierr = MatMult(B,z,x);CHKERRQ(ierr);
317
        } else {
318
          /* standard problem */
319
          ierr = MatMult(A,x,y);CHKERRQ(ierr);
320
        }
321
        ierr = VecAXPY(y,-re,x);CHKERRQ(ierr);
322
        ierr = VecNorm(y,NORM_2,errest+i);CHKERRQ(ierr);
323
      } else {
324
        SETERRQ(PETSC_ERR_SUP,"Residual convergence not supported in non-hermitian problems");
325
      }
1785 antodo 326
    }
1794 antodo 327
    if (errest[i] < eps->tol) conv[i] = PETSC_TRUE;
328
    else conv[i] = PETSC_FALSE;
1785 antodo 329
  }
1794 antodo 330
  ierr = VecDestroy(x);CHKERRQ(ierr);
331
  ierr = VecDestroy(y);CHKERRQ(ierr);
332
  if (B) { ierr = VecDestroy(z);CHKERRQ(ierr); }
1785 antodo 333
  PetscFunctionReturn(0);
334
}
1794 antodo 335
 
336
#undef __FUNCT__  
337
#define __FUNCT__ "EPSComputeSchurVector_Default"
338
/*
339
  EPSComputeSchurVector_Default - this function computes a schur vector during
340
  the solve phase. This function is used by EPSResidualConverged in the subspace,
341
  Arnoldi and Krylov-Schur solvers.
342
*/
343
PetscErrorCode EPSComputeSchurVector_Default(EPS eps,PetscInt i,Vec v)
344
{
345
  PetscErrorCode ierr;
346
  PetscFunctionBegin;
347
  if (i<eps->nconv || i>=eps->nv) {
348
    SETERRQ(PETSC_ERR_ARG_OUTOFRANGE,"Argument out of range");
349
  }
350
  ierr = VecSet(v,0.0);CHKERRQ(ierr);
351
  ierr = VecMAXPY(v,eps->nv,eps->Z+eps->nv*i,eps->V);CHKERRQ(ierr);
352
  PetscFunctionReturn(0);
353
}
354
 
355
#undef __FUNCT__  
356
#define __FUNCT__ "EPSComputeSchurVector_Hermitian"
357
/*
358
  EPSComputeSchurVector_Default - this function computes a schur vector during
359
  the solve phase. This function is used by EPSResidualConverged int the Lanczos
360
  and symmetric Krylov-Schur solvers.
361
*/
362
PetscErrorCode EPSComputeSchurVector_Hermitian(EPS eps,PetscInt i,Vec v)
363
{
364
  PetscErrorCode ierr;
365
  PetscFunctionBegin;
366
  if (i<eps->nconv || i>=eps->nconv+eps->nv) {
367
    SETERRQ(PETSC_ERR_ARG_OUTOFRANGE,"Argument out of range");
368
  }
369
  ierr = VecSet(v,0.0);CHKERRQ(ierr);
370
  ierr = VecMAXPY(v,eps->nv,eps->Z+eps->nv*(i-eps->nconv),eps->V+eps->nconv);CHKERRQ(ierr);
371
  PetscFunctionReturn(0);
1800 jroman 372
}
373
 
374
#undef __FUNCT__  
375
#define __FUNCT__ "EPSBuildBalance_Krylov"
376
/*
377
  EPSBuildBalance_Krylov - uses a Krylov subspace method to compute the
378
  diagonal matrix to be applied for balancing in non-Hermitian problems.
379
*/
380
PetscErrorCode EPSBuildBalance_Krylov(EPS eps)
381
{
382
  Vec            z, p, r;
383
  PetscInt       i, j, n;
384
  PetscScalar    norma;
385
  PetscScalar    *pz, *pr, *pp, *pD;
386
  PetscErrorCode ierr;
387
 
388
  PetscFunctionBegin;
389
  ierr = VecDuplicate(eps->vec_initial,&r);CHKERRQ(ierr);
390
  ierr = VecDuplicate(eps->vec_initial,&p);CHKERRQ(ierr);
391
  ierr = VecDuplicate(eps->vec_initial,&z);CHKERRQ(ierr);
392
  ierr = VecGetLocalSize(z,&n);CHKERRQ(ierr);
393
  ierr = VecSet(eps->D,1.0);CHKERRQ(ierr);
394
 
395
  for (j=0;j<eps->balance_its;j++) {
396
 
397
    /* Build a random vector of +-1's */
398
    ierr = SlepcVecSetRandom(z);CHKERRQ(ierr);
399
    ierr = VecGetArray(z,&pz);CHKERRQ(ierr);
400
    for (i=0;i<n;i++) {
401
      if (pz[i]<0.5) pz[i]=-1.0;
402
      else pz[i]=1.0;
403
    }
404
    ierr = VecRestoreArray(z,&pz);CHKERRQ(ierr);
405
 
406
    /* Compute p=DA(D\z) */
407
    ierr = VecPointwiseDivide(r,z,eps->D);CHKERRQ(ierr);
408
    ierr = STApply(eps->OP,r,p);CHKERRQ(ierr);
409
    ierr = VecPointwiseMult(p,p,eps->D);CHKERRQ(ierr);
1804 jroman 410
    if (j==0) {
411
      /* Estimate the matrix inf-norm */
412
      ierr = VecAbs(p);CHKERRQ(ierr);
413
      ierr = VecMax(p,PETSC_NULL,&norma);CHKERRQ(ierr);
414
    }
1800 jroman 415
    if (eps->balance == EPSBALANCE_TWOSIDE) {
416
      /* Compute r=D\(A'Dz) */
417
      ierr = VecPointwiseMult(z,z,eps->D);CHKERRQ(ierr);
418
      ierr = STApplyTranspose(eps->OP,z,r);CHKERRQ(ierr);
419
      ierr = VecPointwiseDivide(r,r,eps->D);CHKERRQ(ierr);
420
    }
421
 
422
    /* Adjust values of D */
423
    ierr = VecGetArray(r,&pr);CHKERRQ(ierr);
424
    ierr = VecGetArray(p,&pp);CHKERRQ(ierr);
425
    ierr = VecGetArray(eps->D,&pD);CHKERRQ(ierr);
426
    for (i=0;i<n;i++) {
427
      if (eps->balance == EPSBALANCE_TWOSIDE) {
428
        if (PetscAbsScalar(pp[i])>eps->balance_cutoff*norma && pr[i]!=0.0)
429
          pD[i] *= sqrt(PetscAbsScalar(pr[i]/pp[i]));
430
      } else {
431
        if (pp[i]!=0.0) pD[i] *= 1.0/PetscAbsScalar(pp[i]);
432
      }
433
    }
434
    ierr = VecRestoreArray(r,&pr);CHKERRQ(ierr);
435
    ierr = VecRestoreArray(p,&pp);CHKERRQ(ierr);
436
    ierr = VecRestoreArray(eps->D,&pD);CHKERRQ(ierr);
437
  }
438
 
439
  ierr = VecDestroy(r);CHKERRQ(ierr);
440
  ierr = VecDestroy(p);CHKERRQ(ierr);
441
  ierr = VecDestroy(z);CHKERRQ(ierr);
442
  PetscFunctionReturn(0);
443
}
444