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