Actual source code: epssolve.c

slepc-3.7.2 2016-07-19
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: }