Actual source code: qepsolve.c
1: /*
2: QEP routines related to the solution process.
4: - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
5: SLEPc - Scalable Library for Eigenvalue Problem Computations
6: Copyright (c) 2002-2010, Universidad Politecnica de Valencia, Spain
8: This file is part of SLEPc.
9:
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 private/qepimpl.h
28: /*@
29: QEPSolve - Solves the quadratic eigensystem.
31: Collective on QEP
33: Input Parameter:
34: . qep - eigensolver context obtained from QEPCreate()
36: Options Database:
37: + -qep_view - print information about the solver used
38: . -qep_view_binary - save the matrices to the default binary file
39: - -qep_plot_eigs - plot computed eigenvalues
41: Level: beginner
43: .seealso: QEPCreate(), QEPSetUp(), QEPDestroy(), QEPSetTolerances()
44: @*/
45: PetscErrorCode QEPSolve(QEP qep)
46: {
48: PetscInt i;
49: PetscReal re,im;
50: PetscTruth flg;
51: PetscViewer viewer;
52: PetscDraw draw;
53: PetscDrawSP drawsp;
54: char filename[PETSC_MAX_PATH_LEN];
59: flg = PETSC_FALSE;
60: PetscOptionsGetTruth(((PetscObject)qep)->prefix,"-qep_view_binary",&flg,PETSC_NULL);
61: if (flg) {
62: MatView(qep->M,PETSC_VIEWER_BINARY_(((PetscObject)qep)->comm));
63: MatView(qep->C,PETSC_VIEWER_BINARY_(((PetscObject)qep)->comm));
64: MatView(qep->K,PETSC_VIEWER_BINARY_(((PetscObject)qep)->comm));
65: }
67: /* reset the convergence flag from the previous solves */
68: qep->reason = QEP_CONVERGED_ITERATING;
70: if (!qep->setupcalled){ QEPSetUp(qep); }
71: IPResetOperationCounters(qep->ip);
72: qep->nconv = 0;
73: qep->its = 0;
74: qep->matvecs = 0;
75: qep->linits = 0;
76: for (i=0;i<qep->ncv;i++) qep->eigr[i]=qep->eigi[i]=qep->errest[i]=0.0;
77: QEPMonitor(qep,qep->its,qep->nconv,qep->eigr,qep->eigi,qep->errest,qep->ncv);
79: PetscLogEventBegin(QEP_Solve,qep,0,0,0);
80: (*qep->ops->solve)(qep);
81: PetscLogEventEnd(QEP_Solve,qep,0,0,0);
83: if (!qep->reason) {
84: SETERRQ(1,"Internal error, solver returned without setting converged reason");
85: }
87: #ifndef PETSC_USE_COMPLEX
88: /* reorder conjugate eigenvalues (positive imaginary first) */
89: for (i=0;i<qep->nconv-1;i++) {
90: if (qep->eigi[i] != 0) {
91: if (qep->eigi[i] < 0) {
92: qep->eigi[i] = -qep->eigi[i];
93: qep->eigi[i+1] = -qep->eigi[i+1];
94: VecScale(qep->V[i+1],-1.0);
95: }
96: i++;
97: }
98: }
99: #endif
101: /* sort eigenvalues according to qep->which parameter */
102: PetscFree(qep->perm);
103: if (qep->nconv > 0) {
104: PetscMalloc(sizeof(PetscInt)*qep->nconv,&qep->perm);
105: QEPSortEigenvalues(qep,qep->nconv,qep->eigr,qep->eigi,qep->perm);
106: }
108: PetscOptionsGetString(((PetscObject)qep)->prefix,"-qep_view",filename,PETSC_MAX_PATH_LEN,&flg);
109: if (flg && !PetscPreLoadingOn) {
110: PetscViewerASCIIOpen(((PetscObject)qep)->comm,filename,&viewer);
111: QEPView(qep,viewer);
112: PetscViewerDestroy(viewer);
113: }
115: flg = PETSC_FALSE;
116: PetscOptionsGetTruth(((PetscObject)qep)->prefix,"-qep_plot_eigs",&flg,PETSC_NULL);
117: if (flg) {
118: PetscViewerDrawOpen(PETSC_COMM_SELF,0,"Computed Eigenvalues",
119: PETSC_DECIDE,PETSC_DECIDE,300,300,&viewer);
120: PetscViewerDrawGetDraw(viewer,0,&draw);
121: PetscDrawSPCreate(draw,1,&drawsp);
122: for(i=0;i<qep->nconv;i++) {
123: #if defined(PETSC_USE_COMPLEX)
124: re = PetscRealPart(qep->eigr[i]);
125: im = PetscImaginaryPart(qep->eigi[i]);
126: #else
127: re = qep->eigr[i];
128: im = qep->eigi[i];
129: #endif
130: PetscDrawSPAddPoint(drawsp,&re,&im);
131: }
132: PetscDrawSPDraw(drawsp);
133: PetscDrawSPDestroy(drawsp);
134: PetscViewerDestroy(viewer);
135: }
137: /* Remove the initial subspace */
138: qep->nini = 0;
140: return(0);
141: }
145: /*@
146: QEPGetIterationNumber - Gets the current iteration number. If the
147: call to QEPSolve() is complete, then it returns the number of iterations
148: carried out by the solution method.
149:
150: Not Collective
152: Input Parameter:
153: . qep - the quadratic eigensolver context
155: Output Parameter:
156: . its - number of iterations
158: Level: intermediate
160: Note:
161: During the i-th iteration this call returns i-1. If QEPSolve() is
162: complete, then parameter "its" contains either the iteration number at
163: which convergence was successfully reached, or failure was detected.
164: Call QEPGetConvergedReason() to determine if the solver converged or
165: failed and why.
167: .seealso: QEPGetConvergedReason(), QEPSetTolerances()
168: @*/
169: PetscErrorCode QEPGetIterationNumber(QEP qep,PetscInt *its)
170: {
174: *its = qep->its;
175: return(0);
176: }
180: /*@
181: QEPGetConverged - Gets the number of converged eigenpairs.
183: Not Collective
185: Input Parameter:
186: . qep - the quadratic eigensolver context
187:
188: Output Parameter:
189: . nconv - number of converged eigenpairs
191: Note:
192: This function should be called after QEPSolve() has finished.
194: Level: beginner
196: .seealso: QEPSetDimensions(), QEPSolve()
197: @*/
198: PetscErrorCode QEPGetConverged(QEP qep,PetscInt *nconv)
199: {
203: *nconv = qep->nconv;
204: return(0);
205: }
210: /*@C
211: QEPGetConvergedReason - Gets the reason why the QEPSolve() iteration was
212: stopped.
214: Not Collective
216: Input Parameter:
217: . qep - the quadratic eigensolver context
219: Output Parameter:
220: . reason - negative value indicates diverged, positive value converged
222: Possible values for reason:
223: + QEP_CONVERGED_TOL - converged up to tolerance
224: . QEP_DIVERGED_ITS - required more than its to reach convergence
225: - QEP_DIVERGED_BREAKDOWN - generic breakdown in method
227: Note:
228: Can only be called after the call to QEPSolve() is complete.
230: Level: intermediate
232: .seealso: QEPSetTolerances(), QEPSolve(), QEPConvergedReason
233: @*/
234: PetscErrorCode QEPGetConvergedReason(QEP qep,QEPConvergedReason *reason)
235: {
239: *reason = qep->reason;
240: return(0);
241: }
245: /*@
246: QEPGetEigenpair - Gets the i-th solution of the eigenproblem as computed by
247: QEPSolve(). The solution consists in both the eigenvalue and the eigenvector.
249: Not Collective, but vectors are shared by all processors that share the QEP
251: Input Parameters:
252: + qep - quadratic eigensolver context
253: - i - index of the solution
255: Output Parameters:
256: + eigr - real part of eigenvalue
257: . eigi - imaginary part of eigenvalue
258: . Vr - real part of eigenvector
259: - Vi - imaginary part of eigenvector
261: Notes:
262: If the eigenvalue is real, then eigi and Vi are set to zero. If PETSc is
263: configured with complex scalars the eigenvalue is stored
264: directly in eigr (eigi is set to zero) and the eigenvector in Vr (Vi is
265: set to zero).
267: The index i should be a value between 0 and nconv-1 (see QEPGetConverged()).
268: Eigenpairs are indexed according to the ordering criterion established
269: with QEPSetWhichEigenpairs().
271: Level: beginner
273: .seealso: QEPSolve(), QEPGetConverged(), QEPSetWhichEigenpairs()
274: @*/
275: PetscErrorCode QEPGetEigenpair(QEP qep, PetscInt i, PetscScalar *eigr, PetscScalar *eigi, Vec Vr, Vec Vi)
276: {
277: PetscInt k;
282: if (!qep->eigr || !qep->eigi || !qep->V) {
283: SETERRQ(PETSC_ERR_ARG_WRONGSTATE, "QEPSolve must be called first");
284: }
285: if (i<0 || i>=qep->nconv) {
286: SETERRQ(PETSC_ERR_ARG_OUTOFRANGE, "Argument 2 out of range");
287: }
289: if (!qep->perm) k = i;
290: else k = qep->perm[i];
292: /* eigenvalue */
293: #ifdef PETSC_USE_COMPLEX
294: if (eigr) *eigr = qep->eigr[k];
295: if (eigi) *eigi = 0;
296: #else
297: if (eigr) *eigr = qep->eigr[k];
298: if (eigi) *eigi = qep->eigi[k];
299: #endif
300:
301: /* eigenvector */
302: #ifdef PETSC_USE_COMPLEX
303: if (Vr) { VecCopy(qep->V[k],Vr); }
304: if (Vi) { VecSet(Vi,0.0); }
305: #else
306: if (qep->eigi[k]>0) { /* first value of conjugate pair */
307: if (Vr) { VecCopy(qep->V[k],Vr); }
308: if (Vi) { VecCopy(qep->V[k+1],Vi); }
309: } else if (qep->eigi[k]<0) { /* second value of conjugate pair */
310: if (Vr) { VecCopy(qep->V[k-1],Vr); }
311: if (Vi) {
312: VecCopy(qep->V[k],Vi);
313: VecScale(Vi,-1.0);
314: }
315: } else { /* real eigenvalue */
316: if (Vr) { VecCopy(qep->V[k],Vr); }
317: if (Vi) { VecSet(Vi,0.0); }
318: }
319: #endif
320:
321: return(0);
322: }
326: /*@
327: QEPGetErrorEstimate - Returns the error estimate associated to the i-th
328: computed eigenpair.
330: Not Collective
332: Input Parameter:
333: + qep - quadratic eigensolver context
334: - i - index of eigenpair
336: Output Parameter:
337: . errest - the error estimate
339: Notes:
340: This is the error estimate used internally by the eigensolver. The actual
341: error bound can be computed with QEPComputeRelativeError(). See also the users
342: manual for details.
344: Level: advanced
346: .seealso: QEPComputeRelativeError()
347: @*/
348: PetscErrorCode QEPGetErrorEstimate(QEP qep, PetscInt i, PetscReal *errest)
349: {
352: if (!qep->eigr || !qep->eigi) {
353: SETERRQ(PETSC_ERR_ARG_WRONGSTATE, "QEPSolve must be called first");
354: }
355: if (i<0 || i>=qep->nconv) {
356: SETERRQ(PETSC_ERR_ARG_OUTOFRANGE, "Argument 2 out of range");
357: }
358: if (qep->perm) i = qep->perm[i];
359: if (errest) *errest = qep->errest[i];
360: return(0);
361: }
365: /*
366: QEPComputeResidualNorm_Private - Computes the norm of the residual vector
367: associated with an eigenpair.
368: */
369: PetscErrorCode QEPComputeResidualNorm_Private(QEP qep, PetscScalar kr, PetscScalar ki, Vec xr, Vec xi, PetscReal *norm)
370: {
372: Vec u,w;
373: Mat M=qep->M,C=qep->C,K=qep->K;
374: #ifndef PETSC_USE_COMPLEX
375: Vec v,y,z;
376: PetscReal ni,nr;
377: PetscScalar a1,a2;
378: #endif
379:
381: VecDuplicate(qep->V[0],&u);
382: VecDuplicate(u,&w);
383:
384: #ifndef PETSC_USE_COMPLEX
385: if (ki == 0 ||
386: PetscAbsScalar(ki) < PetscAbsScalar(kr*PETSC_MACHINE_EPSILON)) {
387: #endif
388: MatMult(K,xr,u); /* u=K*x */
389: if (PetscAbsScalar(kr) > PETSC_MACHINE_EPSILON) {
390: MatMult(C,xr,w); /* w=C*x */
391: VecAXPY(u,kr,w); /* u=l*C*x+K*x */
392: MatMult(M,xr,w); /* w=M*x */
393: VecAXPY(u,kr*kr,w); /* u=l^2*M*x+l*C*x+K*x */
394: }
395: VecNorm(u,NORM_2,norm);
396: #ifndef PETSC_USE_COMPLEX
397: } else {
398: VecDuplicate(u,&v);
399: VecDuplicate(u,&y);
400: VecDuplicate(u,&z);
401: a1 = kr*kr-ki*ki;
402: a2 = 2.0*kr*ki;
403: MatMult(K,xr,u); /* u=K*xr */
404: if (SlepcAbsEigenvalue(kr,ki) > PETSC_MACHINE_EPSILON) {
405: MatMult(C,xr,v); /* v=C*xr */
406: MatMult(C,xi,w); /* w=C*xi */
407: MatMult(M,xr,y); /* y=M*xr */
408: MatMult(M,xi,z); /* z=M*xi */
409: VecAXPY(u,kr,v); /* u=kr*C*xr+K*xr */
410: VecAXPY(u,-ki,w); /* u=kr*C*xr-ki*C*xi+K*xr */
411: VecAXPY(u,a1,y); /* u=a1*M*xr+kr*C*xr-ki*C*xi+K*xr */
412: VecAXPY(u,-a2,z); /* u=a1*M*xr-a2*M*xi+kr*C*xr-ki*C*xi+K*xr */
413: }
414: VecNorm(u,NORM_2,&nr);
415: MatMult(K,xi,u); /* u=K*xi */
416: if (SlepcAbsEigenvalue(kr,ki) > PETSC_MACHINE_EPSILON) {
417: VecAXPY(u,kr,w); /* u=kr*C*xi+K*xi */
418: VecAXPY(u,ki,v); /* u=kr*C*xi+ki*C*xi+K*xi */
419: VecAXPY(u,a1,z); /* u=a1*M*xi+kr*C*xi+ki*C*xi+K*xi */
420: VecAXPY(u,a2,y); /* u=a1*M*xi+a2*M*ki+kr*C*xi+ki*C*xi+K*xi */
421: }
422: VecNorm(u,NORM_2,&ni);
423: *norm = SlepcAbsEigenvalue(nr,ni);
424: VecDestroy(v);
425: VecDestroy(y);
426: VecDestroy(z);
427: }
428: #endif
430: VecDestroy(w);
431: VecDestroy(u);
432: return(0);
433: }
437: /*@
438: QEPComputeResidualNorm - Computes the norm of the residual vector associated with
439: the i-th computed eigenpair.
441: Collective on QEP
443: Input Parameter:
444: . qep - the quadratic eigensolver context
445: . i - the solution index
447: Output Parameter:
448: . norm - the residual norm, computed as ||(l^2*M+l*C+K)x||_2 where l is the
449: eigenvalue and x is the eigenvector.
450: If l=0 then the residual norm is computed as ||Kx||_2.
452: Notes:
453: The index i should be a value between 0 and nconv-1 (see QEPGetConverged()).
454: Eigenpairs are indexed according to the ordering criterion established
455: with QEPSetWhichEigenpairs().
457: Level: beginner
459: .seealso: QEPSolve(), QEPGetConverged(), QEPSetWhichEigenpairs()
460: @*/
461: PetscErrorCode QEPComputeResidualNorm(QEP qep, PetscInt i, PetscReal *norm)
462: {
464: Vec xr,xi;
465: PetscScalar kr,ki;
466:
470: VecDuplicate(qep->V[0],&xr);
471: VecDuplicate(qep->V[0],&xi);
472: QEPGetEigenpair(qep,i,&kr,&ki,xr,xi);
473: QEPComputeResidualNorm_Private(qep,kr,ki,xr,xi,norm);
474: VecDestroy(xr);
475: VecDestroy(xi);
476: return(0);
477: }
481: /*
482: QEPComputeRelativeError_Private - Computes the relative error bound
483: associated with an eigenpair.
484: */
485: PetscErrorCode QEPComputeRelativeError_Private(QEP qep, PetscScalar kr, PetscScalar ki, Vec xr, Vec xi, PetscReal *error)
486: {
488: PetscReal norm, er;
489: #ifndef PETSC_USE_COMPLEX
490: PetscReal ei;
491: #endif
492:
494: QEPComputeResidualNorm_Private(qep,kr,ki,xr,xi,&norm);
496: #ifndef PETSC_USE_COMPLEX
497: if (ki == 0 ||
498: PetscAbsScalar(ki) < PetscAbsScalar(kr*PETSC_MACHINE_EPSILON)) {
499: #endif
500: VecNorm(xr,NORM_2,&er);
501: if (PetscAbsScalar(kr) > norm) {
502: *error = norm/(PetscAbsScalar(kr)*er);
503: } else {
504: *error = norm/er;
505: }
506: #ifndef PETSC_USE_COMPLEX
507: } else {
508: VecNorm(xr,NORM_2,&er);
509: VecNorm(xi,NORM_2,&ei);
510: if (SlepcAbsEigenvalue(kr,ki) > norm) {
511: *error = norm/(SlepcAbsEigenvalue(kr,ki)*SlepcAbsEigenvalue(er,ei));
512: } else {
513: *error = norm/SlepcAbsEigenvalue(er,ei);
514: }
515: }
516: #endif
517:
518: return(0);
519: }
523: /*@
524: QEPComputeRelativeError - Computes the relative error bound associated
525: with the i-th computed eigenpair.
527: Collective on QEP
529: Input Parameter:
530: . qep - the quadratic eigensolver context
531: . i - the solution index
533: Output Parameter:
534: . error - the relative error bound, computed as ||(l^2*M+l*C+K)x||_2/||lx||_2 where
535: l is the eigenvalue and x is the eigenvector.
536: If l=0 the relative error is computed as ||Kx||_2/||x||_2.
538: Level: beginner
540: .seealso: QEPSolve(), QEPComputeResidualNorm(), QEPGetErrorEstimate()
541: @*/
542: PetscErrorCode QEPComputeRelativeError(QEP qep, PetscInt i, PetscReal *error)
543: {
545: Vec xr,xi;
546: PetscScalar kr,ki;
547:
551: VecDuplicate(qep->V[0],&xr);
552: VecDuplicate(qep->V[0],&xi);
553: QEPGetEigenpair(qep,i,&kr,&ki,xr,xi);
554: QEPComputeRelativeError_Private(qep,kr,ki,xr,xi,error);
555: VecDestroy(xr);
556: VecDestroy(xi);
557: return(0);
558: }
562: /*@
563: QEPSortEigenvalues - Sorts a list of eigenvalues according to the criterion
564: specified via QEPSetWhichEigenpairs().
566: Not Collective
568: Input Parameters:
569: + qep - the quadratic eigensolver context
570: . n - number of eigenvalues in the list
571: . eigr - pointer to the array containing the eigenvalues
572: - eigi - imaginary part of the eigenvalues (only when using real numbers)
574: Output Parameter:
575: . perm - resulting permutation
577: Note:
578: The result is a list of indices in the original eigenvalue array
579: corresponding to the first nev eigenvalues sorted in the specified
580: criterion.
582: Level: developer
584: .seealso: QEPSortEigenvaluesReal(), QEPSetWhichEigenpairs()
585: @*/
586: PetscErrorCode QEPSortEigenvalues(QEP qep,PetscInt n,PetscScalar *eigr,PetscScalar *eigi,PetscInt *perm)
587: {
589: PetscScalar re,im;
590: PetscInt i,j,result,tmp;
593: for (i=0; i<n; i++) { perm[i] = i; }
594: /* insertion sort */
595: for (i=n-1; i>=0; i--) {
596: re = eigr[perm[i]];
597: im = eigi[perm[i]];
598: j = i + 1;
599: #ifndef PETSC_USE_COMPLEX
600: if (im != 0) {
601: /* complex eigenvalue */
602: i--;
603: im = eigi[perm[i]];
604: }
605: #endif
606: while (j<n) {
607: QEPCompareEigenvalues(qep,re,im,eigr[perm[j]],eigi[perm[j]],&result);
608: if (result >= 0) break;
609: #ifndef PETSC_USE_COMPLEX
610: /* keep together every complex conjugated eigenpair */
611: if (im == 0) {
612: if (eigi[perm[j]] == 0) {
613: #endif
614: tmp = perm[j-1]; perm[j-1] = perm[j]; perm[j] = tmp;
615: j++;
616: #ifndef PETSC_USE_COMPLEX
617: } else {
618: tmp = perm[j-1]; perm[j-1] = perm[j]; perm[j] = perm[j+1]; perm[j+1] = tmp;
619: j+=2;
620: }
621: } else {
622: if (eigi[perm[j]] == 0) {
623: tmp = perm[j-2]; perm[j-2] = perm[j]; perm[j] = perm[j-1]; perm[j-1] = tmp;
624: j++;
625: } else {
626: tmp = perm[j-2]; perm[j-2] = perm[j]; perm[j] = tmp;
627: tmp = perm[j-1]; perm[j-1] = perm[j+1]; perm[j+1] = tmp;
628: j+=2;
629: }
630: }
631: #endif
632: }
633: }
634: return(0);
635: }
639: /*@
640: QEPSortEigenvaluesReal - Sorts a list of eigenvalues according to a certain
641: criterion (version for real eigenvalues only).
643: Not Collective
645: Input Parameters:
646: + qep - the quadratic eigensolver context
647: . n - number of eigenvalue in the list
648: - eig - pointer to the array containing the eigenvalues (real)
650: Output Parameter:
651: . perm - resulting permutation
653: Note:
654: The result is a list of indices in the original eigenvalue array
655: corresponding to the first nev eigenvalues sorted in the specified
656: criterion.
658: Level: developer
660: .seealso: QEPSortEigenvalues(), QEPSetWhichEigenpairs(), QEPCompareEigenvalues()
661: @*/
662: PetscErrorCode QEPSortEigenvaluesReal(QEP qep,PetscInt n,PetscReal *eig,PetscInt *perm)
663: {
665: PetscScalar re;
666: PetscInt i,j,result,tmp;
669: for (i=0; i<n; i++) { perm[i] = i; }
670: /* insertion sort */
671: for (i=1; i<n; i++) {
672: re = eig[perm[i]];
673: j = i-1;
674: QEPCompareEigenvalues(qep,re,0.0,eig[perm[j]],0.0,&result);
675: while (result>0 && j>=0) {
676: tmp = perm[j]; perm[j] = perm[j+1]; perm[j+1] = tmp; j--;
677: if (j>=0) {
678: QEPCompareEigenvalues(qep,re,0.0,eig[perm[j]],0.0,&result);
679: }
680: }
681: }
682: return(0);
683: }
687: /*@
688: QEPCompareEigenvalues - Compares two (possibly complex) eigenvalues according
689: to a certain criterion.
691: Not Collective
693: Input Parameters:
694: + qep - the quadratic eigensolver context
695: . ar - real part of the 1st eigenvalue
696: . ai - imaginary part of the 1st eigenvalue
697: . br - real part of the 2nd eigenvalue
698: - bi - imaginary part of the 2nd eigenvalue
700: Output Parameter:
701: . res - result of comparison
703: Notes:
704: Returns an integer less than, equal to, or greater than zero if the first
705: eigenvalue is considered to be respectively less than, equal to, or greater
706: than the second one.
708: The criterion of comparison is related to the 'which' parameter set with
709: QEPSetWhichEigenpairs().
711: Level: developer
713: .seealso: QEPSortEigenvalues(), QEPSetWhichEigenpairs()
714: @*/
715: PetscErrorCode QEPCompareEigenvalues(QEP qep,PetscScalar ar,PetscScalar ai,PetscScalar br,PetscScalar bi,PetscInt *result)
716: {
717: PetscReal a,b;
720: switch(qep->which) {
721: case QEP_LARGEST_MAGNITUDE:
722: case QEP_SMALLEST_MAGNITUDE:
723: a = SlepcAbsEigenvalue(ar,ai);
724: b = SlepcAbsEigenvalue(br,bi);
725: break;
726: case QEP_LARGEST_REAL:
727: case QEP_SMALLEST_REAL:
728: a = PetscRealPart(ar);
729: b = PetscRealPart(br);
730: break;
731: case QEP_LARGEST_IMAGINARY:
732: case QEP_SMALLEST_IMAGINARY:
733: #if defined(PETSC_USE_COMPLEX)
734: a = PetscImaginaryPart(ar);
735: b = PetscImaginaryPart(br);
736: #else
737: a = PetscAbsReal(ai);
738: b = PetscAbsReal(bi);
739: #endif
740: break;
741: default: SETERRQ(1,"Wrong value of which");
742: }
743: switch(qep->which) {
744: case QEP_LARGEST_MAGNITUDE:
745: case QEP_LARGEST_REAL:
746: case QEP_LARGEST_IMAGINARY:
747: if (a<b) *result = -1;
748: else if (a>b) *result = 1;
749: else *result = 0;
750: break;
751: default:
752: if (a>b) *result = -1;
753: else if (a<b) *result = 1;
754: else *result = 0;
755: }
756: return(0);
757: }
761: /*@
762: QEPGetOperationCounters - Gets the total number of matrix-vector products, dot
763: products, and linear solve iterations used by the QEP object during the last
764: QEPSolve() call.
766: Not Collective
768: Input Parameter:
769: . qep - quadratic eigensolver context
771: Output Parameter:
772: + matvecs - number of matrix-vector product operations
773: . dots - number of dot product operations
774: - lits - number of linear iterations
776: Notes:
777: These counters are reset to zero at each successive call to QEPSolve().
779: Level: intermediate
781: @*/
782: PetscErrorCode QEPGetOperationCounters(QEP qep,PetscInt* matvecs,PetscInt* dots,PetscInt* lits)
783: {
785:
788: if (matvecs) *matvecs = qep->matvecs;
789: if (dots) {
790: IPGetOperationCounters(qep->ip,dots);
791: }
792: if (lits) *lits = qep->linits;
793: return(0);
794: }