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(), EPSConvergedReason267: @*/
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 EPS286: 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 EPS338: 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 EPS439: 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 EPS611: 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: }