Actual source code: epsdefault.c

slepc-3.6.1 2015-09-03
Report Typos and Errors
  1: /*
  2:      This file contains some simple default routines for common operations.

  4:    - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
  5:    SLEPc - Scalable Library for Eigenvalue Problem Computations
  6:    Copyright (c) 2002-2015, Universitat Politecnica de Valencia, Spain

  8:    This file is part of SLEPc.

 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.

 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.

 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/>.
 21:    - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
 22: */

 24: #include <slepc/private/epsimpl.h>   /*I "slepceps.h" I*/
 25: #include <slepcvec.h>

 29: PetscErrorCode EPSBackTransform_Default(EPS eps)
 30: {

 34:   STBackTransform(eps->st,eps->nconv,eps->eigr,eps->eigi);
 35:   return(0);
 36: }

 40: /*
 41:   EPSComputeVectors_Hermitian - Copies the Lanczos vectors as eigenvectors
 42:   using purification for generalized eigenproblems.
 43:  */
 44: PetscErrorCode EPSComputeVectors_Hermitian(EPS eps)
 45: {
 47:   PetscInt       i;
 48:   PetscReal      norm;
 49:   Vec            w,z;

 52:   if (eps->isgeneralized && eps->purify) {
 53:     /* Purify eigenvectors */
 54:     BVCreateVec(eps->V,&w);
 55:     for (i=0;i<eps->nconv;i++) {
 56:       BVCopyVec(eps->V,i,w);
 57:       BVGetColumn(eps->V,i,&z);
 58:       STApply(eps->st,w,z);
 59:       BVRestoreColumn(eps->V,i,&z);
 60:       BVNormColumn(eps->V,i,NORM_2,&norm);
 61:       BVScaleColumn(eps->V,i,1.0/norm);
 62:     }
 63:     VecDestroy(&w);
 64:   }
 65:   return(0);
 66: }

 70: /*
 71:   EPSComputeVectors_Indefinite - similar to the Schur version but
 72:   for indefinite problems
 73:  */
 74: PetscErrorCode EPSComputeVectors_Indefinite(EPS eps)
 75: {
 77:   PetscInt       n,i;
 78:   Mat            X;
 79:   Vec            v,z;
 80: #if !defined(PETSC_USE_COMPLEX)
 81:   Vec            v1;
 82:   PetscScalar    tmp;
 83:   PetscReal      norm,normi;
 84: #endif

 87:   DSGetDimensions(eps->ds,&n,NULL,NULL,NULL,NULL);
 88:   DSVectors(eps->ds,DS_MAT_X,NULL,NULL);
 89:   DSGetMat(eps->ds,DS_MAT_X,&X);
 90:   BVSetActiveColumns(eps->V,0,n);
 91:   BVMultInPlace(eps->V,X,0,n);
 92:   MatDestroy(&X);

 94:   /* purification */
 95:   if (eps->purify) {
 96:     BVCreateVec(eps->V,&v);
 97:     for (i=0;i<eps->nconv;i++) {
 98:       BVCopyVec(eps->V,i,v);
 99:       BVGetColumn(eps->V,i,&z);
100:       STApply(eps->st,v,z);
101:       BVRestoreColumn(eps->V,i,&z);
102:     }
103:     VecDestroy(&v);
104:   }

106:   /* normalization */
107:   for (i=0;i<n;i++) {
108: #if !defined(PETSC_USE_COMPLEX)
109:     if (eps->eigi[i] != 0.0) {
110:       BVGetColumn(eps->V,i,&v);
111:       BVGetColumn(eps->V,i+1,&v1);
112:       VecNorm(v,NORM_2,&norm);
113:       VecNorm(v1,NORM_2,&normi);
114:       tmp = 1.0 / SlepcAbsEigenvalue(norm,normi);
115:       VecScale(v,tmp);
116:       VecScale(v1,tmp);
117:       BVRestoreColumn(eps->V,i,&v);
118:       BVRestoreColumn(eps->V,i+1,&v1);
119:       i++;
120:     } else
121: #endif
122:     {
123:       BVGetColumn(eps->V,i,&v);
124:       VecNormalize(v,NULL);
125:       BVRestoreColumn(eps->V,i,&v);
126:     }
127:   }
128:   return(0);
129: }

133: /*
134:   EPSComputeVectors_Schur - Compute eigenvectors from the vectors
135:   provided by the eigensolver. This version is intended for solvers
136:   that provide Schur vectors. Given the partial Schur decomposition
137:   OP*V=V*T, the following steps are performed:
138:       1) compute eigenvectors of T: T*Z=Z*D
139:       2) compute eigenvectors of OP: X=V*Z
140:  */
141: PetscErrorCode EPSComputeVectors_Schur(EPS eps)
142: {
144:   PetscInt       n,i;
145:   Mat            Z;
146:   Vec            w,z,v;
147: #if !defined(PETSC_USE_COMPLEX)
148:   Vec            v1;
149:   PetscScalar    tmp;
150:   PetscReal      norm,normi;
151: #endif

154:   if (eps->ishermitian) {
155:     if (eps->isgeneralized && !eps->ispositive) {
156:        EPSComputeVectors_Indefinite(eps);
157:     } else {
158:       EPSComputeVectors_Hermitian(eps);
159:     }
160:     return(0);
161:   }
162:   DSGetDimensions(eps->ds,&n,NULL,NULL,NULL,NULL);

164:   /* right eigenvectors */
165:   DSVectors(eps->ds,DS_MAT_X,NULL,NULL);

167:   /* V = V * Z */
168:   DSGetMat(eps->ds,DS_MAT_X,&Z);
169:   BVSetActiveColumns(eps->V,0,n);
170:   BVMultInPlace(eps->V,Z,0,n);
171:   MatDestroy(&Z);

173:   /* Purify eigenvectors */
174:   if (eps->ispositive && eps->purify) {
175:     BVCreateVec(eps->V,&w);
176:     for (i=0;i<n;i++) {
177:       BVCopyVec(eps->V,i,w);
178:       BVGetColumn(eps->V,i,&z);
179:       STApply(eps->st,w,z);
180:       BVRestoreColumn(eps->V,i,&z);
181:     }
182:     VecDestroy(&w);
183:   }

185:   /* Fix eigenvectors if balancing was used */
186:   if (eps->balance!=EPS_BALANCE_NONE && eps->D) {
187:     for (i=0;i<n;i++) {
188:       BVGetColumn(eps->V,i,&z);
189:       VecPointwiseDivide(z,z,eps->D);
190:       BVRestoreColumn(eps->V,i,&z);
191:     }
192:   }

194:   /* normalize eigenvectors (when using purification or balancing) */
195:   if ((eps->ispositive && eps->purify) || (eps->balance!=EPS_BALANCE_NONE && eps->D)) {
196:     for (i=0;i<n;i++) {
197: #if !defined(PETSC_USE_COMPLEX)
198:       if (eps->eigi[i] != 0.0) {
199:         BVGetColumn(eps->V,i,&v);
200:         BVGetColumn(eps->V,i+1,&v1);
201:         VecNorm(v,NORM_2,&norm);
202:         VecNorm(v1,NORM_2,&normi);
203:         tmp = 1.0 / SlepcAbsEigenvalue(norm,normi);
204:         VecScale(v,tmp);
205:         VecScale(v1,tmp);
206:         BVRestoreColumn(eps->V,i,&v);
207:         BVRestoreColumn(eps->V,i+1,&v1);
208:         i++;
209:       } else
210: #endif
211:       {
212:         BVGetColumn(eps->V,i,&v);
213:         VecNormalize(v,NULL);
214:         BVRestoreColumn(eps->V,i,&v);
215:       }
216:     }
217:   }
218:   return(0);
219: }

223: /*@
224:    EPSSetWorkVecs - Sets a number of work vectors into an EPS object.

226:    Collective on EPS

228:    Input Parameters:
229: +  eps - eigensolver context
230: -  nw  - number of work vectors to allocate

232:    Developers Note:
233:    This is PETSC_EXTERN because it may be required by user plugin EPS
234:    implementations.

236:    Level: developer
237: @*/
238: PetscErrorCode EPSSetWorkVecs(EPS eps,PetscInt nw)
239: {
241:   Vec            t;

244:   if (eps->nwork < nw) {
245:     VecDestroyVecs(eps->nwork,&eps->work);
246:     eps->nwork = nw;
247:     BVGetColumn(eps->V,0,&t);
248:     VecDuplicateVecs(t,nw,&eps->work);
249:     BVRestoreColumn(eps->V,0,&t);
250:     PetscLogObjectParents(eps,nw,eps->work);
251:   }
252:   return(0);
253: }

257: /*
258:   EPSSetWhichEigenpairs_Default - Sets the default value for which,
259:   depending on the ST.
260:  */
261: PetscErrorCode EPSSetWhichEigenpairs_Default(EPS eps)
262: {
263:   PetscBool      target;

267:   PetscObjectTypeCompareAny((PetscObject)eps->st,&target,STSINVERT,STCAYLEY,"");
268:   if (target) eps->which = EPS_TARGET_MAGNITUDE;
269:   else eps->which = EPS_LARGEST_MAGNITUDE;
270:   return(0);
271: }

275: /*
276:   EPSConvergedEigRelative - Checks convergence relative to the eigenvalue.
277: */
278: PetscErrorCode EPSConvergedEigRelative(EPS eps,PetscScalar eigr,PetscScalar eigi,PetscReal res,PetscReal *errest,void *ctx)
279: {
280:   PetscReal w;

283:   w = SlepcAbsEigenvalue(eigr,eigi);
284:   *errest = res/w;
285:   return(0);
286: }

290: /*
291:   EPSConvergedAbsolute - Checks convergence absolutely.
292: */
293: PetscErrorCode EPSConvergedAbsolute(EPS eps,PetscScalar eigr,PetscScalar eigi,PetscReal res,PetscReal *errest,void *ctx)
294: {
296:   *errest = res;
297:   return(0);
298: }

302: /*
303:   EPSConvergedNormRelative - Checks convergence relative to the eigenvalue and
304:   the matrix norms.
305: */
306: PetscErrorCode EPSConvergedNormRelative(EPS eps,PetscScalar eigr,PetscScalar eigi,PetscReal res,PetscReal *errest,void *ctx)
307: {
308:   PetscReal w;

311:   w = SlepcAbsEigenvalue(eigr,eigi);
312:   *errest = res / (eps->nrma + w*eps->nrmb);
313:   return(0);
314: }

318: /*
319:   EPSComputeRitzVector - Computes the current Ritz vector.

321:   Simple case (complex scalars or real scalars with Zi=NULL):
322:     x = V*Zr  (V is a basis of nv vectors, Zr has length nv)

324:   Split case:
325:     x = V*Zr  y = V*Zi  (Zr and Zi have length nv)
326: */
327: PetscErrorCode EPSComputeRitzVector(EPS eps,PetscScalar *Zr,PetscScalar *Zi,BV V,Vec x,Vec y)
328: {
330:   PetscReal      norm;
331: #if !defined(PETSC_USE_COMPLEX)
332:   Vec            z;
333: #endif

336:   /* compute eigenvector */
337:   BVMultVec(V,1.0,0.0,x,Zr);

339:   /* purify eigenvector in positive generalized problems */
340:   if (eps->ispositive && eps->purify) {
341:     STApply(eps->st,x,y);
342:     if (eps->ishermitian) {
343:       BVNormVec(eps->V,y,NORM_2,&norm);
344:     } else {
345:       VecNorm(y,NORM_2,&norm);
346:     }
347:     VecScale(y,1.0/norm);
348:     VecCopy(y,x);
349:   }
350:   /* fix eigenvector if balancing is used */
351:   if (!eps->ishermitian && eps->balance!=EPS_BALANCE_NONE && eps->D) {
352:     VecPointwiseDivide(x,x,eps->D);
353:     VecNormalize(x,&norm);
354:   }
355: #if !defined(PETSC_USE_COMPLEX)
356:   /* compute imaginary part of eigenvector */
357:   if (Zi) {
358:     BVMultVec(V,1.0,0.0,y,Zi);
359:     if (eps->ispositive) {
360:       BVCreateVec(V,&z);
361:       STApply(eps->st,y,z);
362:       VecNorm(z,NORM_2,&norm);
363:       VecScale(z,1.0/norm);
364:       VecCopy(z,y);
365:       VecDestroy(&z);
366:     }
367:     if (eps->balance!=EPS_BALANCE_NONE && eps->D) {
368:       VecPointwiseDivide(y,y,eps->D);
369:       VecNormalize(y,&norm);
370:     }
371:   } else
372: #endif
373:   { VecSet(y,0.0); }
374:   return(0);
375: }

379: /*
380:   EPSBuildBalance_Krylov - uses a Krylov subspace method to compute the
381:   diagonal matrix to be applied for balancing in non-Hermitian problems.
382: */
383: PetscErrorCode EPSBuildBalance_Krylov(EPS eps)
384: {
385:   Vec               z,p,r;
386:   PetscInt          i,j;
387:   PetscReal         norma;
388:   PetscScalar       *pz,*pD;
389:   const PetscScalar *pr,*pp;
390:   PetscErrorCode    ierr;

393:   EPSSetWorkVecs(eps,3);
394:   r = eps->work[0];
395:   p = eps->work[1];
396:   z = eps->work[2];
397:   VecSet(eps->D,1.0);

399:   for (j=0;j<eps->balance_its;j++) {

401:     /* Build a random vector of +-1's */
402:     VecSetRandom(z,eps->rand);
403:     VecGetArray(z,&pz);
404:     for (i=0;i<eps->nloc;i++) {
405:       if (PetscRealPart(pz[i])<0.5) pz[i]=-1.0;
406:       else pz[i]=1.0;
407:     }
408:     VecRestoreArray(z,&pz);

410:     /* Compute p=DA(D\z) */
411:     VecPointwiseDivide(r,z,eps->D);
412:     STApply(eps->st,r,p);
413:     VecPointwiseMult(p,p,eps->D);
414:     if (j==0) {
415:       /* Estimate the matrix inf-norm */
416:       VecAbs(p);
417:       VecMax(p,NULL,&norma);
418:     }
419:     if (eps->balance == EPS_BALANCE_TWOSIDE) {
420:       /* Compute r=D\(A'Dz) */
421:       VecPointwiseMult(z,z,eps->D);
422:       STApplyTranspose(eps->st,z,r);
423:       VecPointwiseDivide(r,r,eps->D);
424:     }

426:     /* Adjust values of D */
427:     VecGetArrayRead(r,&pr);
428:     VecGetArrayRead(p,&pp);
429:     VecGetArray(eps->D,&pD);
430:     for (i=0;i<eps->nloc;i++) {
431:       if (eps->balance == EPS_BALANCE_TWOSIDE) {
432:         if (PetscAbsScalar(pp[i])>eps->balance_cutoff*norma && pr[i]!=0.0)
433:           pD[i] *= PetscSqrtReal(PetscAbsScalar(pr[i]/pp[i]));
434:       } else {
435:         if (pp[i]!=0.0) pD[i] *= 1.0/PetscAbsScalar(pp[i]);
436:       }
437:     }
438:     VecRestoreArrayRead(r,&pr);
439:     VecRestoreArrayRead(p,&pp);
440:     VecRestoreArray(eps->D,&pD);
441:   }
442:   return(0);
443: }