Date: 2016-03-29T14:57:44+00:00

Actual source code: epsdefault.c
slepc-3.6.3 2016-03-29
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: }