Date: 2015-09-03T15:04:32+00:00

Actual source code: epssolve.c
slepc-3.6.1 2015-09-03
Report Typos and Errors

      1: /*
      2:       EPS routines related to the solution process.

      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 <petscdraw.h>

     29: PetscErrorCode EPSComputeVectors(EPS eps)
     30: {

     34:   EPSCheckSolved(eps,1);
     35:   switch (eps->state) {
     36:   case EPS_STATE_SOLVED:
     37:     if (eps->ops->computevectors) {
     38:       (*eps->ops->computevectors)(eps);
     39:     }
     40:     break;
     41:   default:
     42:     break;
     43:   }
     44:   eps->state = EPS_STATE_EIGENVECTORS;
     45:   return(0);
     46: }

     50: /*@
     51:    EPSSolve - Solves the eigensystem.

     53:    Collective on EPS

     55:    Input Parameter:
     56: .  eps - eigensolver context obtained from EPSCreate()

     58:    Options Database Keys:
     59: +  -eps_view - print information about the solver used
     60: .  -eps_view_mat0 binary - save the first matrix (A) to the default binary viewer
     61: .  -eps_view_mat1 binary - save the second matrix (B) to the default binary viewer
     62: .  -eps_view_vectors binary - save the computed eigenvectors to the default binary viewer
     63: .  -eps_view_values - print computed eigenvalues
     64: .  -eps_converged_reason - print reason for convergence, and number of iterations
     65: .  -eps_error_absolute - print absolute errors of each eigenpair
     66: .  -eps_error_relative - print relative errors of each eigenpair
     67: -  -eps_error_backward - print backward errors of each eigenpair

     69:    Level: beginner

     71: .seealso: EPSCreate(), EPSSetUp(), EPSDestroy(), EPSSetTolerances()
     72: @*/
     73: PetscErrorCode EPSSolve(EPS eps)
     74: {
     76:   PetscInt       i,nmat;
     77:   PetscScalar    dot;
     78:   PetscBool      iscayley;
     79:   STMatMode      matmode;
     80:   Mat            A,B;
     81:   Vec            w,x;

     85:   PetscLogEventBegin(EPS_Solve,eps,0,0,0);

     87:   /* call setup */
     88:   EPSSetUp(eps);
     89:   eps->nconv = 0;
     90:   eps->its   = 0;
     91:   for (i=0;i<eps->ncv;i++) {
     92:     eps->eigr[i]   = 0.0;
     93:     eps->eigi[i]   = 0.0;
     94:     eps->errest[i] = 0.0;
     95:     eps->perm[i]   = i;
     96:   }
     97:   EPSMonitor(eps,eps->its,eps->nconv,eps->eigr,eps->eigi,eps->errest,eps->ncv);
     98:   EPSViewFromOptions(eps,NULL,"-eps_view_pre");

    100:   /* call solver */
    101:   (*eps->ops->solve)(eps);
    102:   eps->state = EPS_STATE_SOLVED;

    104:   STGetMatMode(eps->st,&matmode);
    105:   if (matmode == ST_MATMODE_INPLACE && eps->ispositive) {
    106:     /* Purify eigenvectors before reverting operator */
    107:     EPSComputeVectors(eps);
    108:   }
    109:   STPostSolve(eps->st);

    111:   if (!eps->reason) SETERRQ(PetscObjectComm((PetscObject)eps),PETSC_ERR_PLIB,"Internal error, solver returned without setting converged reason");

    113:   /* Map eigenvalues back to the original problem, necessary in some
    114:   * spectral transformations */
    115:   if (eps->ops->backtransform) {
    116:     (*eps->ops->backtransform)(eps);
    117:   }

    119: #if !defined(PETSC_USE_COMPLEX)
    120:   /* reorder conjugate eigenvalues (positive imaginary first) */
    121:   for (i=0; i<eps->nconv-1; i++) {
    122:     if (eps->eigi[i] != 0) {
    123:       if (eps->eigi[i] < 0) {
    124:         eps->eigi[i] = -eps->eigi[i];
    125:         eps->eigi[i+1] = -eps->eigi[i+1];
    126:         /* the next correction only works with eigenvectors */
    127:         EPSComputeVectors(eps);
    128:         BVScaleColumn(eps->V,i+1,-1.0);
    129:       }
    130:       i++;
    131:     }
    132:   }
    133: #endif

    135:   STGetNumMatrices(eps->st,&nmat);
    136:   STGetOperators(eps->st,0,&A);
    137:   if (nmat>1) { STGetOperators(eps->st,1,&B); }

    139:   /* In the case of Cayley transform, eigenvectors need to be B-normalized */
    140:   PetscObjectTypeCompare((PetscObject)eps->st,STCAYLEY,&iscayley);
    141:   if (iscayley && eps->isgeneralized && eps->ishermitian) {
    142:     MatCreateVecs(B,NULL,&w);
    143:     EPSComputeVectors(eps);
    144:     for (i=0;i<eps->nconv;i++) {
    145:       BVGetColumn(eps->V,i,&x);
    146:       MatMult(B,x,w);
    147:       VecDot(w,x,&dot);
    148:       VecScale(x,1.0/PetscSqrtScalar(dot));
    149:       BVRestoreColumn(eps->V,i,&x);
    150:     }
    151:     VecDestroy(&w);
    152:   }

    154:   /* sort eigenvalues according to eps->which parameter */
    155:   SlepcSortEigenvalues(eps->sc,eps->nconv,eps->eigr,eps->eigi,eps->perm);
    156:   PetscLogEventEnd(EPS_Solve,eps,0,0,0);

    158:   /* various viewers */
    159:   EPSViewFromOptions(eps,NULL,"-eps_view");
    160:   EPSReasonViewFromOptions(eps);
    161:   EPSErrorViewFromOptions(eps);
    162:   EPSValuesViewFromOptions(eps);
    163:   EPSVectorsViewFromOptions(eps);
    164:   MatViewFromOptions(A,(PetscObject)eps,"-eps_view_mat0");
    165:   if (nmat>1) { MatViewFromOptions(B,(PetscObject)eps,"-eps_view_mat1"); }

    167:   /* Remove deflation and initial subspaces */
    168:   if (eps->nds) {
    169:     BVSetNumConstraints(eps->V,0);
    170:     eps->nds = 0;
    171:   }
    172:   eps->nini = 0;
    173:   return(0);
    174: }

    178: /*@
    179:    EPSGetIterationNumber - Gets the current iteration number. If the
    180:    call to EPSSolve() is complete, then it returns the number of iterations
    181:    carried out by the solution method.

    183:    Not Collective

    185:    Input Parameter:
    186: .  eps - the eigensolver context

    188:    Output Parameter:
    189: .  its - number of iterations

    191:    Level: intermediate

    193:    Note:
    194:    During the i-th iteration this call returns i-1. If EPSSolve() is
    195:    complete, then parameter "its" contains either the iteration number at
    196:    which convergence was successfully reached, or failure was detected.
    197:    Call EPSGetConvergedReason() to determine if the solver converged or
    198:    failed and why.

    200: .seealso: EPSGetConvergedReason(), EPSSetTolerances()
    201: @*/
    202: PetscErrorCode EPSGetIterationNumber(EPS eps,PetscInt *its)
    203: {
    207:   *its = eps->its;
    208:   return(0);
    209: }

    213: /*@
    214:    EPSGetConverged - Gets the number of converged eigenpairs.

    216:    Not Collective

    218:    Input Parameter:
    219: .  eps - the eigensolver context

    221:    Output Parameter:
    222: .  nconv - number of converged eigenpairs

    224:    Note:
    225:    This function should be called after EPSSolve() has finished.

    227:    Level: beginner

    229: .seealso: EPSSetDimensions(), EPSSolve()
    230: @*/
    231: PetscErrorCode EPSGetConverged(EPS eps,PetscInt *nconv)
    232: {
    236:   EPSCheckSolved(eps,1);
    237:   *nconv = eps->nconv;
    238:   return(0);
    239: }

    243: /*@
    244:    EPSGetConvergedReason - Gets the reason why the EPSSolve() iteration was
    245:    stopped.

    247:    Not Collective

    249:    Input Parameter:
    250: .  eps - the eigensolver context

    252:    Output Parameter:
    253: .  reason - negative value indicates diverged, positive value converged

    255:    Possible values for reason:
    256: +  EPS_CONVERGED_TOL - converged up to tolerance
    257: .  EPS_DIVERGED_ITS - required more than its to reach convergence
    258: .  EPS_DIVERGED_BREAKDOWN - generic breakdown in method
    259: -  EPS_DIVERGED_SYMMETRY_LOST - pseudo-Lanczos was not able to keep symmetry

    261:    Note:
    262:    Can only be called after the call to EPSSolve() is complete.

    264:    Level: intermediate

    266: .seealso: EPSSetTolerances(), EPSSolve(), EPSConvergedReason
    267: @*/
    268: PetscErrorCode EPSGetConvergedReason(EPS eps,EPSConvergedReason *reason)
    269: {
    273:   EPSCheckSolved(eps,1);
    274:   *reason = eps->reason;
    275:   return(0);
    276: }

    280: /*@
    281:    EPSGetInvariantSubspace - Gets an orthonormal basis of the computed invariant
    282:    subspace.

    284:    Not Collective, but vectors are shared by all processors that share the EPS

    286:    Input Parameter:
    287: .  eps - the eigensolver context

    289:    Output Parameter:
    290: .  v - an array of vectors

    292:    Notes:
    293:    This function should be called after EPSSolve() has finished.

    295:    The user should provide in v an array of nconv vectors, where nconv is
    296:    the value returned by EPSGetConverged().

    298:    The first k vectors returned in v span an invariant subspace associated
    299:    with the first k computed eigenvalues (note that this is not true if the
    300:    k-th eigenvalue is complex and matrix A is real; in this case the first
    301:    k+1 vectors should be used). An invariant subspace X of A satisfies Ax
    302:    in X for all x in X (a similar definition applies for generalized
    303:    eigenproblems).

    305:    Level: intermediate

    307: .seealso: EPSGetEigenpair(), EPSGetConverged(), EPSSolve()
    308: @*/
    309: PetscErrorCode EPSGetInvariantSubspace(EPS eps,Vec *v)
    310: {
    312:   PetscInt       i;

    318:   EPSCheckSolved(eps,1);
    319:   if (!eps->ishermitian && eps->state==EPS_STATE_EIGENVECTORS) SETERRQ(PetscObjectComm((PetscObject)eps),PETSC_ERR_ARG_WRONGSTATE,"EPSGetInvariantSubspace must be called before EPSGetEigenpair,EPSGetEigenvector or EPSComputeError");
    320:   for (i=0;i<eps->nconv;i++) {
    321:     BVCopyVec(eps->V,i,v[i]);
    322:     if (eps->balance!=EPS_BALANCE_NONE && eps->D) {
    323:       VecPointwiseDivide(v[i],v[i],eps->D);
    324:       VecNormalize(v[i],NULL);
    325:     }
    326:   }
    327:   return(0);
    328: }

    332: /*@
    333:    EPSGetEigenpair - Gets the i-th solution of the eigenproblem as computed by
    334:    EPSSolve(). The solution consists in both the eigenvalue and the eigenvector.

    336:    Logically Collective on EPS

    338:    Input Parameters:
    339: +  eps - eigensolver context
    340: -  i   - index of the solution

    342:    Output Parameters:
    343: +  eigr - real part of eigenvalue
    344: .  eigi - imaginary part of eigenvalue
    345: .  Vr   - real part of eigenvector
    346: -  Vi   - imaginary part of eigenvector

    348:    Notes:
    349:    It is allowed to pass NULL for Vr and Vi, if the eigenvector is not
    350:    required. Otherwise, the caller must provide valid Vec objects, i.e.,
    351:    they must be created by the calling program with e.g. MatCreateVecs().

    353:    If the eigenvalue is real, then eigi and Vi are set to zero. If PETSc is
    354:    configured with complex scalars the eigenvalue is stored
    355:    directly in eigr (eigi is set to zero) and the eigenvector in Vr (Vi is
    356:    set to zero). In both cases, the user can pass NULL in eigi and Vi.

    358:    The index i should be a value between 0 and nconv-1 (see EPSGetConverged()).
    359:    Eigenpairs are indexed according to the ordering criterion established
    360:    with EPSSetWhichEigenpairs().

    362:    The 2-norm of the eigenvector is one unless the problem is generalized
    363:    Hermitian. In this case the eigenvector is normalized with respect to the
    364:    norm defined by the B matrix.

    366:    Level: beginner

    368: .seealso: EPSGetEigenvalue(), EPSGetEigenvector(), EPSSolve(),
    369:           EPSGetConverged(), EPSSetWhichEigenpairs(), EPSGetInvariantSubspace()
    370: @*/
    371: PetscErrorCode EPSGetEigenpair(EPS eps,PetscInt i,PetscScalar *eigr,PetscScalar *eigi,Vec Vr,Vec Vi)
    372: {

    378:   EPSCheckSolved(eps,1);
    379:   if (i<0 || i>=eps->nconv) SETERRQ(PetscObjectComm((PetscObject)eps),PETSC_ERR_ARG_OUTOFRANGE,"Argument 2 out of range");
    380:   EPSGetEigenvalue(eps,i,eigr,eigi);
    381:   if (Vr || Vi) { EPSGetEigenvector(eps,i,Vr,Vi); }
    382:   return(0);
    383: }

    387: /*@
    388:    EPSGetEigenvalue - Gets the i-th eigenvalue as computed by EPSSolve().

    390:    Not Collective

    392:    Input Parameters:
    393: +  eps - eigensolver context
    394: -  i   - index of the solution

    396:    Output Parameters:
    397: +  eigr - real part of eigenvalue
    398: -  eigi - imaginary part of eigenvalue

    400:    Notes:
    401:    If the eigenvalue is real, then eigi is set to zero. If PETSc is
    402:    configured with complex scalars the eigenvalue is stored
    403:    directly in eigr (eigi is set to zero).

    405:    The index i should be a value between 0 and nconv-1 (see EPSGetConverged()).
    406:    Eigenpairs are indexed according to the ordering criterion established
    407:    with EPSSetWhichEigenpairs().

    409:    Level: beginner

    411: .seealso: EPSSolve(), EPSGetConverged(), EPSSetWhichEigenpairs(), EPSGetEigenpair()
    412: @*/
    413: PetscErrorCode EPSGetEigenvalue(EPS eps,PetscInt i,PetscScalar *eigr,PetscScalar *eigi)
    414: {
    415:   PetscInt k;

    419:   EPSCheckSolved(eps,1);
    420:   if (i<0 || i>=eps->nconv) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_OUTOFRANGE,"Argument 2 out of range");
    421:   k = eps->perm[i];
    422: #if defined(PETSC_USE_COMPLEX)
    423:   if (eigr) *eigr = eps->eigr[k];
    424:   if (eigi) *eigi = 0;
    425: #else
    426:   if (eigr) *eigr = eps->eigr[k];
    427:   if (eigi) *eigi = eps->eigi[k];
    428: #endif
    429:   return(0);
    430: }

    434: /*@
    435:    EPSGetEigenvector - Gets the i-th right eigenvector as computed by EPSSolve().

    437:    Logically Collective on EPS

    439:    Input Parameters:
    440: +  eps - eigensolver context
    441: -  i   - index of the solution

    443:    Output Parameters:
    444: +  Vr   - real part of eigenvector
    445: -  Vi   - imaginary part of eigenvector

    447:    Notes:
    448:    The caller must provide valid Vec objects, i.e., they must be created
    449:    by the calling program with e.g. MatCreateVecs().

    451:    If the corresponding eigenvalue is real, then Vi is set to zero. If PETSc is
    452:    configured with complex scalars the eigenvector is stored
    453:    directly in Vr (Vi is set to zero). In both cases, the user can pass NULL in Vi.

    455:    The index i should be a value between 0 and nconv-1 (see EPSGetConverged()).
    456:    Eigenpairs are indexed according to the ordering criterion established
    457:    with EPSSetWhichEigenpairs().

    459:    The 2-norm of the eigenvector is one unless the problem is generalized
    460:    Hermitian. In this case the eigenvector is normalized with respect to the
    461:    norm defined by the B matrix.

    463:    Level: beginner

    465: .seealso: EPSSolve(), EPSGetConverged(), EPSSetWhichEigenpairs(), EPSGetEigenpair()
    466: @*/
    467: PetscErrorCode EPSGetEigenvector(EPS eps,PetscInt i,Vec Vr,Vec Vi)
    468: {
    470:   PetscInt       k;

    478:   EPSCheckSolved(eps,1);
    479:   if (i<0 || i>=eps->nconv) SETERRQ(PetscObjectComm((PetscObject)eps),PETSC_ERR_ARG_OUTOFRANGE,"Argument 2 out of range");
    480:   EPSComputeVectors(eps);
    481:   k = eps->perm[i];
    482: #if defined(PETSC_USE_COMPLEX)
    483:   BVCopyVec(eps->V,k,Vr);
    484:   if (Vi) { VecSet(Vi,0.0); }
    485: #else
    486:   if (eps->eigi[k] > 0) { /* first value of conjugate pair */
    487:     BVCopyVec(eps->V,k,Vr);
    488:     if (Vi) {
    489:       BVCopyVec(eps->V,k+1,Vi);
    490:     }
    491:   } else if (eps->eigi[k] < 0) { /* second value of conjugate pair */
    492:     BVCopyVec(eps->V,k-1,Vr);
    493:     if (Vi) {
    494:       BVCopyVec(eps->V,k,Vi);
    495:       VecScale(Vi,-1.0);
    496:     }
    497:   } else { /* real eigenvalue */
    498:     BVCopyVec(eps->V,k,Vr);
    499:     if (Vi) { VecSet(Vi,0.0); }
    500:   }
    501: #endif
    502:   return(0);
    503: }

    507: /*@
    508:    EPSGetErrorEstimate - Returns the error estimate associated to the i-th
    509:    computed eigenpair.

    511:    Not Collective

    513:    Input Parameter:
    514: +  eps - eigensolver context
    515: -  i   - index of eigenpair

    517:    Output Parameter:
    518: .  errest - the error estimate

    520:    Notes:
    521:    This is the error estimate used internally by the eigensolver. The actual
    522:    error bound can be computed with EPSComputeError(). See also the users
    523:    manual for details.

    525:    Level: advanced

    527: .seealso: EPSComputeError()
    528: @*/
    529: PetscErrorCode EPSGetErrorEstimate(EPS eps,PetscInt i,PetscReal *errest)
    530: {
    534:   EPSCheckSolved(eps,1);
    535:   if (i<0 || i>=eps->nconv) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_OUTOFRANGE,"Argument 2 out of range");
    536:   if (errest) *errest = eps->errest[eps->perm[i]];
    537:   return(0);
    538: }

    542: /*
    543:    EPSComputeResidualNorm_Private - Computes the norm of the residual vector
    544:    associated with an eigenpair.

    546:    Input Parameters:
    547:      kr,ki - eigenvalue
    548:      xr,xi - eigenvector
    549:      z     - three work vectors (the second one not referenced in complex scalars)
    550: */
    551: PetscErrorCode EPSComputeResidualNorm_Private(EPS eps,PetscScalar kr,PetscScalar ki,Vec xr,Vec xi,Vec *z,PetscReal *norm)
    552: {
    554:   PetscInt       nmat;
    555:   Mat            A,B;
    556:   Vec            u,w;
    557: #if !defined(PETSC_USE_COMPLEX)
    558:   Vec            v;
    559:   PetscReal      ni,nr;
    560: #endif

    563:   u = z[0]; w = z[2];
    564:   STGetNumMatrices(eps->st,&nmat);
    565:   STGetOperators(eps->st,0,&A);
    566:   if (nmat>1) { STGetOperators(eps->st,1,&B); }

    568: #if !defined(PETSC_USE_COMPLEX)
    569:   v = z[1];
    570:   if (ki == 0 || PetscAbsScalar(ki) < PetscAbsScalar(kr*PETSC_MACHINE_EPSILON)) {
    571: #endif
    572:     MatMult(A,xr,u);                             /* u=A*x */
    573:     if (PetscAbsScalar(kr) > PETSC_MACHINE_EPSILON) {
    574:       if (eps->isgeneralized) { MatMult(B,xr,w); }
    575:       else { VecCopy(xr,w); }                    /* w=B*x */
    576:       VecAXPY(u,-kr,w);                          /* u=A*x-k*B*x */
    577:     }
    578:     VecNorm(u,NORM_2,norm);
    579: #if !defined(PETSC_USE_COMPLEX)
    580:   } else {
    581:     MatMult(A,xr,u);                             /* u=A*xr */
    582:     if (SlepcAbsEigenvalue(kr,ki) > PETSC_MACHINE_EPSILON) {
    583:       if (eps->isgeneralized) { MatMult(B,xr,v); }
    584:       else { VecCopy(xr,v); }                    /* v=B*xr */
    585:       VecAXPY(u,-kr,v);                          /* u=A*xr-kr*B*xr */
    586:       if (eps->isgeneralized) { MatMult(B,xi,w); }
    587:       else { VecCopy(xi,w); }                    /* w=B*xi */
    588:       VecAXPY(u,ki,w);                           /* u=A*xr-kr*B*xr+ki*B*xi */
    589:     }
    590:     VecNorm(u,NORM_2,&nr);
    591:     MatMult(A,xi,u);                             /* u=A*xi */
    592:     if (SlepcAbsEigenvalue(kr,ki) > PETSC_MACHINE_EPSILON) {
    593:       VecAXPY(u,-kr,w);                          /* u=A*xi-kr*B*xi */
    594:       VecAXPY(u,-ki,v);                          /* u=A*xi-kr*B*xi-ki*B*xr */
    595:     }
    596:     VecNorm(u,NORM_2,&ni);
    597:     *norm = SlepcAbsEigenvalue(nr,ni);
    598:   }
    599: #endif
    600:   return(0);
    601: }

    605: /*@
    606:    EPSComputeError - Computes the error (based on the residual norm) associated
    607:    with the i-th computed eigenpair.

    609:    Collective on EPS

    611:    Input Parameter:
    612: +  eps  - the eigensolver context
    613: .  i    - the solution index
    614: -  type - the type of error to compute

    616:    Output Parameter:
    617: .  error - the error

    619:    Notes:
    620:    The error can be computed in various ways, all of them based on the residual
    621:    norm ||Ax-kBx||_2 where k is the eigenvalue and x is the eigenvector.

    623:    Level: beginner

    625: .seealso: EPSErrorType, EPSSolve(), EPSGetErrorEstimate()
    626: @*/
    627: PetscErrorCode EPSComputeError(EPS eps,PetscInt i,EPSErrorType type,PetscReal *error)
    628: {
    630:   Mat            A,B;
    631:   Vec            xr,xi,w[3];
    632:   PetscReal      t;
    633:   PetscScalar    kr,ki;
    634:   PetscBool      flg;

    641:   EPSCheckSolved(eps,1);

    643:   /* allocate work vectors */
    644: #if defined(PETSC_USE_COMPLEX)
    645:   EPSSetWorkVecs(eps,3);
    646:   xi   = NULL;
    647:   w[1] = NULL;
    648: #else
    649:   EPSSetWorkVecs(eps,5);
    650:   xi   = eps->work[3];
    651:   w[1] = eps->work[4];
    652: #endif
    653:   xr   = eps->work[0];
    654:   w[0] = eps->work[1];
    655:   w[2] = eps->work[2];

    657:   /* compute residual norms */
    658:   EPSGetEigenpair(eps,i,&kr,&ki,xr,xi);
    659:   EPSComputeResidualNorm_Private(eps,kr,ki,xr,xi,w,error);

    661:   /* compute error */
    662:   switch (type) {
    663:     case EPS_ERROR_ABSOLUTE:
    664:       break;
    665:     case EPS_ERROR_RELATIVE:
    666:       *error /= SlepcAbsEigenvalue(kr,ki);
    667:       break;
    668:     case EPS_ERROR_BACKWARD:
    669:       /* initialization of matrix norms */
    670:       if (!eps->nrma) {
    671:         STGetOperators(eps->st,0,&A);
    672:         MatHasOperation(A,MATOP_NORM,&flg);
    673:         if (!flg) SETERRQ(PetscObjectComm((PetscObject)eps),PETSC_ERR_ARG_WRONG,"The computation of backward errors requires a matrix norm operation");
    674:         MatNorm(A,NORM_INFINITY,&eps->nrma);
    675:       }
    676:       if (eps->isgeneralized) {
    677:         if (!eps->nrmb) {
    678:           STGetOperators(eps->st,1,&B);
    679:           MatHasOperation(B,MATOP_NORM,&flg);
    680:           if (!flg) SETERRQ(PetscObjectComm((PetscObject)eps),PETSC_ERR_ARG_WRONG,"The computation of backward errors requires a matrix norm operation");
    681:           MatNorm(B,NORM_INFINITY,&eps->nrmb);
    682:         }
    683:       } else eps->nrmb = 1.0;
    684:       t = SlepcAbsEigenvalue(kr,ki);
    685:       *error /= eps->nrma+t*eps->nrmb;
    686:       break;
    687:     default:
    688:       SETERRQ(PetscObjectComm((PetscObject)eps),PETSC_ERR_ARG_OUTOFRANGE,"Invalid error type");
    689:   }
    690:   return(0);
    691: }

    695: /*
    696:    EPSGetStartVector - Generate a suitable vector to be used as the starting vector
    697:    for the recurrence that builds the right subspace.

    699:    Collective on EPS and Vec

    701:    Input Parameters:
    702: +  eps - the eigensolver context
    703: -  i   - iteration number

    705:    Output Parameters:
    706: .  breakdown - flag indicating that a breakdown has occurred

    708:    Notes:
    709:    The start vector is computed from another vector: for the first step (i=0),
    710:    the first initial vector is used (see EPSSetInitialSpace()); otherwise a random
    711:    vector is created. Then this vector is forced to be in the range of OP (only
    712:    for generalized definite problems) and orthonormalized with respect to all
    713:    V-vectors up to i-1. The resulting vector is placed in V[i].

    715:    The flag breakdown is set to true if either i=0 and the vector belongs to the
    716:    deflation space, or i>0 and the vector is linearly dependent with respect
    717:    to the V-vectors.
    718: */
    719: PetscErrorCode EPSGetStartVector(EPS eps,PetscInt i,PetscBool *breakdown)
    720: {
    722:   PetscReal      norm;
    723:   PetscBool      lindep;
    724:   Vec            w,z;

    730:   /* For the first step, use the first initial vector, otherwise a random one */
    731:   if (i>0 || eps->nini==0) {
    732:     BVSetRandomColumn(eps->V,i,eps->rand);
    733:   }
    734:   BVCreateVec(eps->V,&w);
    735:   BVCopyVec(eps->V,i,w);

    737:   /* Force the vector to be in the range of OP for definite generalized problems */
    738:   BVGetColumn(eps->V,i,&z);
    739:   if (eps->ispositive || (eps->isgeneralized && eps->ishermitian)) {
    740:     STApply(eps->st,w,z);
    741:   } else {
    742:     VecCopy(w,z);
    743:   }
    744:   BVRestoreColumn(eps->V,i,&z);
    745:   VecDestroy(&w);

    747:   /* Orthonormalize the vector with respect to previous vectors */
    748:   BVOrthogonalizeColumn(eps->V,i,NULL,&norm,&lindep);
    749:   if (breakdown) *breakdown = lindep;
    750:   else if (lindep || norm == 0.0) {
    751:     if (i==0) SETERRQ(PetscObjectComm((PetscObject)eps),1,"Initial vector is zero or belongs to the deflation space");
    752:     else SETERRQ(PetscObjectComm((PetscObject)eps),1,"Unable to generate more start vectors");
    753:   }
    754:   BVScaleColumn(eps->V,i,1.0/norm);
    755:   return(0);
    756: }