Date: 2016-09-29T11:11:16+00:00

Actual source code: epssolve.c
slepc-3.7.3 2016-09-29
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-2016, 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:   if (eps->state>=EPS_STATE_SOLVED) return(0);
     86:   PetscLogEventBegin(EPS_Solve,eps,0,0,0);

     88:   /* call setup */
     89:   EPSSetUp(eps);
     90:   eps->nconv = 0;
     91:   eps->its   = 0;
     92:   for (i=0;i<eps->ncv;i++) {
     93:     eps->eigr[i]   = 0.0;
     94:     eps->eigi[i]   = 0.0;
     95:     eps->errest[i] = 0.0;
     96:     eps->perm[i]   = i;
     97:   }
     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 && nmat>1 && 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:    Notes:

    257:    Possible values for reason are
    258: +  EPS_CONVERGED_TOL - converged up to tolerance
    259: .  EPS_CONVERGED_USER - converged due to a user-defined condition
    260: .  EPS_DIVERGED_ITS - required more than max_it iterations to reach convergence
    261: .  EPS_DIVERGED_BREAKDOWN - generic breakdown in method
    262: -  EPS_DIVERGED_SYMMETRY_LOST - pseudo-Lanczos was not able to keep symmetry

    264:    Can only be called after the call to EPSSolve() is complete.

    266:    Level: intermediate

    268: .seealso: EPSSetTolerances(), EPSSolve(), EPSConvergedReason
    269: @*/
    270: PetscErrorCode EPSGetConvergedReason(EPS eps,EPSConvergedReason *reason)
    271: {
    275:   EPSCheckSolved(eps,1);
    276:   *reason = eps->reason;
    277:   return(0);
    278: }

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

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

    288:    Input Parameter:
    289: .  eps - the eigensolver context

    291:    Output Parameter:
    292: .  v - an array of vectors

    294:    Notes:
    295:    This function should be called after EPSSolve() has finished.

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

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

    307:    Level: intermediate

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

    320:   EPSCheckSolved(eps,1);
    321:   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");
    322:   for (i=0;i<eps->nconv;i++) {
    323:     BVCopyVec(eps->V,i,v[i]);
    324:     if (eps->balance!=EPS_BALANCE_NONE && eps->D) {
    325:       VecPointwiseDivide(v[i],v[i],eps->D);
    326:       VecNormalize(v[i],NULL);
    327:     }
    328:   }
    329:   return(0);
    330: }

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

    338:    Logically Collective on EPS

    340:    Input Parameters:
    341: +  eps - eigensolver context
    342: -  i   - index of the solution

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

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

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

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

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

    368:    Level: beginner

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

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

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

    392:    Not Collective

    394:    Input Parameters:
    395: +  eps - eigensolver context
    396: -  i   - index of the solution

    398:    Output Parameters:
    399: +  eigr - real part of eigenvalue
    400: -  eigi - imaginary part of eigenvalue

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

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

    411:    Level: beginner

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

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

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

    439:    Logically Collective on EPS

    441:    Input Parameters:
    442: +  eps - eigensolver context
    443: -  i   - index of the solution

    445:    Output Parameters:
    446: +  Vr   - real part of eigenvector
    447: -  Vi   - imaginary part of eigenvector

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

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

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

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

    465:    Level: beginner

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

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

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

    513:    Not Collective

    515:    Input Parameter:
    516: +  eps - eigensolver context
    517: -  i   - index of eigenpair

    519:    Output Parameter:
    520: .  errest - the error estimate

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

    527:    Level: advanced

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

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

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

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

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

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

    611:    Collective on EPS

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

    618:    Output Parameter:
    619: .  error - the error

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

    625:    Level: beginner

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

    643:   EPSCheckSolved(eps,1);

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

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

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

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

    701:    Collective on EPS and Vec

    703:    Input Parameters:
    704: +  eps - the eigensolver context
    705: -  i   - iteration number

    707:    Output Parameters:
    708: .  breakdown - flag indicating that a breakdown has occurred

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

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

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

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

    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: }