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(), EPSConvergedReason269: @*/
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 EPS288: 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 EPS340: 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 EPS441: 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 EPS613: 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: }
736: BVCreateVec(eps->V,&w);
737: BVCopyVec(eps->V,i,w);
739: /* Force the vector to be in the range of OP for definite generalized problems */
740: BVGetColumn(eps->V,i,&z);
741: if (eps->ispositive || (eps->isgeneralized && eps->ishermitian)) {
742: STApply(eps->st,w,z);
743: } else {
744: VecCopy(w,z);
745: }
746: BVRestoreColumn(eps->V,i,&z);
747: VecDestroy(&w);
749: /* Orthonormalize the vector with respect to previous vectors */
750: BVOrthogonalizeColumn(eps->V,i,NULL,&norm,&lindep);
751: if (breakdown) *breakdown = lindep;
752: else if (lindep || norm == 0.0) {
753: if (i==0) SETERRQ(PetscObjectComm((PetscObject)eps),1,"Initial vector is zero or belongs to the deflation space");
754: else SETERRQ(PetscObjectComm((PetscObject)eps),1,"Unable to generate more start vectors");
755: }
756: BVScaleColumn(eps->V,i,1.0/norm);
757: return(0);
758: }