Actual source code: nepsolve.c
1: /*
2: NEP routines related to the solution process.
4: - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
5: SLEPc - Scalable Library for Eigenvalue Problem Computations
6: Copyright (c) 2002-2013, 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/nepimpl.h> /*I "slepcnep.h" I*/
25: #include <petscdraw.h>
29: /*@
30: NEPSolve - Solves the nonlinear eigensystem.
32: Collective on NEP
34: Input Parameter:
35: . nep - eigensolver context obtained from NEPCreate()
37: Options Database Keys:
38: + -nep_view - print information about the solver used
39: - -nep_plot_eigs - plot computed eigenvalues
41: Level: beginner
43: .seealso: NEPCreate(), NEPSetUp(), NEPDestroy(), NEPSetTolerances()
44: @*/
45: PetscErrorCode NEPSolve(NEP nep)
46: {
47: PetscErrorCode ierr;
48: PetscInt i;
49: PetscReal re,im;
50: PetscBool flg;
51: PetscViewer viewer;
52: PetscViewerFormat format;
53: PetscDraw draw;
54: PetscDrawSP drawsp;
58: PetscLogEventBegin(NEP_Solve,nep,0,0,0);
60: /* call setup */
61: NEPSetUp(nep);
62: nep->nconv = 0;
63: nep->its = 0;
64: for (i=0;i<nep->ncv;i++) {
65: nep->eig[i] = 0.0;
66: nep->errest[i] = 0.0;
67: }
68: nep->ktol = 0.1;
69: NEPMonitor(nep,nep->its,nep->nconv,nep->eig,nep->errest,nep->ncv);
71: DSSetEigenvalueComparison(nep->ds,nep->comparison,nep->comparisonctx);
73: (*nep->ops->solve)(nep);
75: if (!nep->reason) SETERRQ(PetscObjectComm((PetscObject)nep),PETSC_ERR_PLIB,"Internal error, solver returned without setting converged reason");
77: /* sort eigenvalues according to nep->which parameter */
78: NEPSortEigenvalues(nep,nep->nconv,nep->eig,nep->perm);
80: PetscLogEventEnd(NEP_Solve,nep,0,0,0);
82: /* various viewers */
83: PetscOptionsGetViewer(PetscObjectComm((PetscObject)nep),((PetscObject)nep)->prefix,"-nep_view",&viewer,&format,&flg);
84: if (flg && !PetscPreLoadingOn) {
85: PetscViewerPushFormat(viewer,format);
86: NEPView(nep,viewer);
87: PetscViewerPopFormat(viewer);
88: PetscViewerDestroy(&viewer);
89: }
91: flg = PETSC_FALSE;
92: PetscOptionsGetBool(((PetscObject)nep)->prefix,"-nep_plot_eigs",&flg,NULL);
93: if (flg) {
94: PetscViewerDrawOpen(PETSC_COMM_SELF,0,"Computed Eigenvalues",PETSC_DECIDE,PETSC_DECIDE,300,300,&viewer);
95: PetscViewerDrawGetDraw(viewer,0,&draw);
96: PetscDrawSPCreate(draw,1,&drawsp);
97: for (i=0;i<nep->nconv;i++) {
98: re = PetscRealPart(nep->eig[i]);
99: im = PetscImaginaryPart(nep->eig[i]);
100: PetscDrawSPAddPoint(drawsp,&re,&im);
101: }
102: PetscDrawSPDraw(drawsp,PETSC_TRUE);
103: PetscDrawSPDestroy(&drawsp);
104: PetscViewerDestroy(&viewer);
105: }
107: /* Remove the initial subspace */
108: nep->nini = 0;
109: return(0);
110: }
114: PetscErrorCode NEP_KSPSolve(NEP nep,Vec b,Vec x)
115: {
117: PetscInt lits;
120: KSPSolve(nep->ksp,b,x);
121: KSPGetIterationNumber(nep->ksp,&lits);
122: nep->linits += lits;
123: PetscInfo2(nep,"iter=%D, linear solve iterations=%D\n",nep->its,lits);
124: return(0);
125: }
129: /*@
130: NEPProjectOperator - Computes the projection of the nonlinear operator.
132: Collective on NEP
134: Input Parameters:
135: + nep - the nonlinear eigensolver context
136: . j0 - initial index
137: . j1 - final index
138: - f - workspace vector
140: Notes:
141: This is available for split operator only.
143: The nonlinear operator T(lambda) is projected onto span(V), where V is
144: an orthonormal basis built internally by the solver. The projected
145: operator is equal to sum_i V'*A_i*V*f_i(lambda), so this function
146: computes all matrices Ei = V'*A_i*V, and stores them in the extra
147: matrices inside DS. Only rows/columns in the range [j0,j1-1] are computed,
148: the previous ones are assumed to be available already.
150: Level: developer
152: .seealso: NEPSetSplitOperator()
153: @*/
154: PetscErrorCode NEPProjectOperator(NEP nep,PetscInt j0,PetscInt j1,Vec f)
155: {
157: PetscInt i,j,k,ld;
158: PetscScalar *G,val;
159: Vec *V = nep->V;
160: PetscBool isherm,set,flg;
167: if (!nep->split) SETERRQ(PetscObjectComm((PetscObject)nep),PETSC_ERR_ARG_WRONGSTATE,"This solver requires a split operator");
168: DSGetLeadingDimension(nep->ds,&ld);
169: for (k=0;k<nep->nt;k++) {
170: DSGetArray(nep->ds,DSMatExtra[k],&G);
171: MatIsHermitianKnown(nep->A[k],&set,&flg);
172: isherm = set? flg: PETSC_FALSE;
173: for (j=j0;j<j1;j++) {
174: if (!isherm) {
175: if (j>0) { MatMultHermitianTranspose(nep->A[k],V[j],f); }
176: VecMDot(f,j,V,G+j*ld);
177: for (i=0;i<j;i++)
178: G[j+i*ld] = PetscConj(G[i+j*ld]);
179: }
180: MatMult(nep->A[k],V[j],f);
181: VecDot(f,V[j],&val);
182: G[j+j*ld] = val;
183: VecMDot(f,j,V,G+j*ld);
184: if (isherm) {
185: for (i=0;i<j;i++)
186: G[j+i*ld] = PetscConj(G[i+j*ld]);
187: }
188: }
189: DSRestoreArray(nep->ds,DSMatExtra[k],&G);
190: }
191: return(0);
192: }
196: /*@
197: NEPApplyFunction - Applies the nonlinear function T(lambda) to a given vector.
199: Collective on NEP
201: Input Parameters:
202: + nep - the nonlinear eigensolver context
203: . lambda - scalar argument
204: . x - vector to be multiplied against
205: - v - workspace vector
207: Output Parameters:
208: + y - result vector
209: . A - Function matrix
210: . B - optional preconditioning matrix
211: - flg - flag indicating matrix structure (see MatStructure enum)
213: Note:
214: If the nonlinear operator is represented in split form, the result
215: y = T(lambda)*x is computed without building T(lambda) explicitly. In
216: that case, parameters A, B and flg are not used. Otherwise, the matrix
217: T(lambda) is built and the effect is the same as a call to
218: NEPComputeFunction() followed by a MatMult().
220: Level: developer
222: .seealso: NEPSetSplitOperator(), NEPComputeFunction()
223: @*/
224: PetscErrorCode NEPApplyFunction(NEP nep,PetscScalar lambda,Vec x,Vec v,Vec y,Mat *A,Mat *B,MatStructure *flg)
225: {
227: PetscInt i;
228: PetscScalar alpha;
236: if (nep->split) {
237: VecZeroEntries(y);
238: for (i=0;i<nep->nt;i++) {
239: FNEvaluateFunction(nep->f[i],lambda,&alpha);
240: MatMult(nep->A[i],x,v);
241: VecAXPY(y,alpha,v);
242: }
243: } else {
244: NEPComputeFunction(nep,lambda,A,B,flg);
245: MatMult(*A,x,y);
246: }
247: return(0);
248: }
252: /*@
253: NEPApplyJacobian - Applies the nonlinear Jacobian T'(lambda) to a given vector.
255: Collective on NEP
257: Input Parameters:
258: + nep - the nonlinear eigensolver context
259: . lambda - scalar argument
260: . x - vector to be multiplied against
261: - v - workspace vector
263: Output Parameters:
264: + y - result vector
265: . A - Jacobian matrix
266: - flg - flag indicating matrix structure (see MatStructure enum)
268: Note:
269: If the nonlinear operator is represented in split form, the result
270: y = T'(lambda)*x is computed without building T'(lambda) explicitly. In
271: that case, parameters A and flg are not used. Otherwise, the matrix
272: T'(lambda) is built and the effect is the same as a call to
273: NEPComputeJacobian() followed by a MatMult().
275: Level: developer
277: .seealso: NEPSetSplitOperator(), NEPComputeJacobian()
278: @*/
279: PetscErrorCode NEPApplyJacobian(NEP nep,PetscScalar lambda,Vec x,Vec v,Vec y,Mat *A,MatStructure *flg)
280: {
282: PetscInt i;
283: PetscScalar alpha;
291: if (nep->split) {
292: VecZeroEntries(y);
293: for (i=0;i<nep->nt;i++) {
294: FNEvaluateDerivative(nep->f[i],lambda,&alpha);
295: MatMult(nep->A[i],x,v);
296: VecAXPY(y,alpha,v);
297: }
298: } else {
299: NEPComputeJacobian(nep,lambda,A,flg);
300: MatMult(*A,x,y);
301: }
302: return(0);
303: }
307: /*@
308: NEPGetIterationNumber - Gets the current iteration number. If the
309: call to NEPSolve() is complete, then it returns the number of iterations
310: carried out by the solution method.
312: Not Collective
314: Input Parameter:
315: . nep - the nonlinear eigensolver context
317: Output Parameter:
318: . its - number of iterations
320: Level: intermediate
322: Note:
323: During the i-th iteration this call returns i-1. If NEPSolve() is
324: complete, then parameter "its" contains either the iteration number at
325: which convergence was successfully reached, or failure was detected.
326: Call NEPGetConvergedReason() to determine if the solver converged or
327: failed and why.
329: .seealso: NEPGetConvergedReason(), NEPSetTolerances()
330: @*/
331: PetscErrorCode NEPGetIterationNumber(NEP nep,PetscInt *its)
332: {
336: *its = nep->its;
337: return(0);
338: }
342: /*@
343: NEPGetConverged - Gets the number of converged eigenpairs.
345: Not Collective
347: Input Parameter:
348: . nep - the nonlinear eigensolver context
350: Output Parameter:
351: . nconv - number of converged eigenpairs
353: Note:
354: This function should be called after NEPSolve() has finished.
356: Level: beginner
358: .seealso: NEPSetDimensions(), NEPSolve()
359: @*/
360: PetscErrorCode NEPGetConverged(NEP nep,PetscInt *nconv)
361: {
365: *nconv = nep->nconv;
366: return(0);
367: }
371: /*@C
372: NEPGetConvergedReason - Gets the reason why the NEPSolve() iteration was
373: stopped.
375: Not Collective
377: Input Parameter:
378: . nep - the nonlinear eigensolver context
380: Output Parameter:
381: . reason - negative value indicates diverged, positive value converged
383: Possible values for reason:
384: + NEP_CONVERGED_FNORM_ABS - function norm satisfied absolute tolerance
385: . NEP_CONVERGED_FNORM_RELATIVE - function norm satisfied relative tolerance
386: . NEP_CONVERGED_SNORM_RELATIVE - step norm satisfied relative tolerance
387: . NEP_DIVERGED_LINEAR_SOLVE - inner linear solve failed
388: . NEP_DIVERGED_FUNCTION_COUNT - reached maximum allowed function evaluations
389: . NEP_DIVERGED_MAX_IT - required more than its to reach convergence
390: . NEP_DIVERGED_BREAKDOWN - generic breakdown in method
391: - NEP_DIVERGED_FNORM_NAN - Inf or NaN detected in function evaluation
393: Note:
394: Can only be called after the call to NEPSolve() is complete.
396: Level: intermediate
398: .seealso: NEPSetTolerances(), NEPSolve(), NEPConvergedReason
399: @*/
400: PetscErrorCode NEPGetConvergedReason(NEP nep,NEPConvergedReason *reason)
401: {
405: *reason = nep->reason;
406: return(0);
407: }
411: /*@
412: NEPGetEigenpair - Gets the i-th solution of the eigenproblem as computed by
413: NEPSolve(). The solution consists in both the eigenvalue and the eigenvector.
415: Logically Collective on NEP
417: Input Parameters:
418: + nep - nonlinear eigensolver context
419: - i - index of the solution
421: Output Parameters:
422: + eig - eigenvalue
423: - V - eigenvector
425: Notes:
426: If PETSc is configured with real scalars, then complex eigenpairs cannot
427: be obtained. Users should use a complex-scalar configuration. This
428: behaviour is different to other SLEPc solvers such as EPS.
430: The index i should be a value between 0 and nconv-1 (see NEPGetConverged()).
431: Eigenpairs are indexed according to the ordering criterion established
432: with NEPSetWhichEigenpairs().
434: Level: beginner
436: .seealso: NEPSolve(), NEPGetConverged(), NEPSetWhichEigenpairs()
437: @*/
438: PetscErrorCode NEPGetEigenpair(NEP nep,PetscInt i,PetscScalar *eig,Vec V)
439: {
440: PetscInt k;
447: if (!nep->eig || !nep->V) SETERRQ(PetscObjectComm((PetscObject)nep),PETSC_ERR_ARG_WRONGSTATE,"NEPSolve must be called first");
448: if (i<0 || i>=nep->nconv) SETERRQ(PetscObjectComm((PetscObject)nep),PETSC_ERR_ARG_OUTOFRANGE,"Argument 2 out of range");
450: if (!nep->perm) k = i;
451: else k = nep->perm[i];
453: if (eig) *eig = nep->eig[k];
454: if (V) { VecCopy(nep->V[k],V); }
455: return(0);
456: }
460: /*@
461: NEPGetErrorEstimate - Returns the error estimate associated to the i-th
462: computed eigenpair.
464: Not Collective
466: Input Parameter:
467: + nep - nonlinear eigensolver context
468: - i - index of eigenpair
470: Output Parameter:
471: . errest - the error estimate
473: Notes:
474: This is the error estimate used internally by the eigensolver. The actual
475: error bound can be computed with NEPComputeRelativeError().
477: Level: advanced
479: .seealso: NEPComputeRelativeError()
480: @*/
481: PetscErrorCode NEPGetErrorEstimate(NEP nep,PetscInt i,PetscReal *errest)
482: {
486: if (!nep->eig) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_WRONGSTATE,"NEPSolve must be called first");
487: if (i<0 || i>=nep->nconv) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_OUTOFRANGE,"Argument 2 out of range");
488: if (nep->perm) i = nep->perm[i];
489: if (errest) *errest = nep->errest[i];
490: return(0);
491: }
495: /*
496: NEPComputeResidualNorm_Private - Computes the norm of the residual vector
497: associated with an eigenpair.
498: */
499: PetscErrorCode NEPComputeResidualNorm_Private(NEP nep,PetscScalar lambda,Vec x,PetscReal *norm)
500: {
502: Vec u;
503: Mat T=nep->function;
504: MatStructure mats;
507: VecDuplicate(nep->V[0],&u);
508: NEPComputeFunction(nep,lambda,&T,&T,&mats);
509: MatMult(T,x,u);
510: VecNorm(u,NORM_2,norm);
511: VecDestroy(&u);
512: return(0);
513: }
517: /*@
518: NEPComputeResidualNorm - Computes the norm of the residual vector associated with
519: the i-th computed eigenpair.
521: Collective on NEP
523: Input Parameter:
524: + nep - the nonlinear eigensolver context
525: - i - the solution index
527: Output Parameter:
528: . norm - the residual norm, computed as ||T(lambda)x||_2 where lambda is the
529: eigenvalue and x is the eigenvector.
531: Notes:
532: The index i should be a value between 0 and nconv-1 (see NEPGetConverged()).
533: Eigenpairs are indexed according to the ordering criterion established
534: with NEPSetWhichEigenpairs().
536: Level: beginner
538: .seealso: NEPSolve(), NEPGetConverged(), NEPSetWhichEigenpairs()
539: @*/
540: PetscErrorCode NEPComputeResidualNorm(NEP nep,PetscInt i,PetscReal *norm)
541: {
543: Vec x;
544: PetscScalar lambda;
550: VecDuplicate(nep->V[0],&x);
551: NEPGetEigenpair(nep,i,&lambda,x);
552: NEPComputeResidualNorm_Private(nep,lambda,x,norm);
553: VecDestroy(&x);
554: return(0);
555: }
559: /*
560: NEPComputeRelativeError_Private - Computes the relative error bound
561: associated with an eigenpair.
562: */
563: PetscErrorCode NEPComputeRelativeError_Private(NEP nep,PetscScalar lambda,Vec x,PetscReal *error)
564: {
566: PetscReal norm,er;
569: NEPComputeResidualNorm_Private(nep,lambda,x,&norm);
570: VecNorm(x,NORM_2,&er);
571: if (PetscAbsScalar(lambda) > norm) {
572: *error = norm/(PetscAbsScalar(lambda)*er);
573: } else {
574: *error = norm/er;
575: }
576: return(0);
577: }
581: /*@
582: NEPComputeRelativeError - Computes the relative error bound associated
583: with the i-th computed eigenpair.
585: Collective on NEP
587: Input Parameter:
588: + nep - the nonlinear eigensolver context
589: - i - the solution index
591: Output Parameter:
592: . error - the relative error bound, computed as ||T(lambda)x||_2/||lambda*x||_2
593: where lambda is the eigenvalue and x is the eigenvector.
594: If lambda=0 the relative error is computed as ||T(lambda)x||_2/||x||_2.
596: Level: beginner
598: .seealso: NEPSolve(), NEPComputeResidualNorm(), NEPGetErrorEstimate()
599: @*/
600: PetscErrorCode NEPComputeRelativeError(NEP nep,PetscInt i,PetscReal *error)
601: {
603: Vec x;
604: PetscScalar lambda;
610: VecDuplicate(nep->V[0],&x);
611: NEPGetEigenpair(nep,i,&lambda,x);
612: NEPComputeRelativeError_Private(nep,lambda,x,error);
613: VecDestroy(&x);
614: return(0);
615: }
619: /*@
620: NEPSortEigenvalues - Sorts a list of eigenvalues according to the criterion
621: specified via NEPSetWhichEigenpairs().
623: Not Collective
625: Input Parameters:
626: + nep - the nonlinear eigensolver context
627: . n - number of eigenvalues in the list
628: - eig - pointer to the array containing the eigenvalues
630: Output Parameter:
631: . perm - resulting permutation
633: Note:
634: The result is a list of indices in the original eigenvalue array
635: corresponding to the first nev eigenvalues sorted in the specified
636: criterion.
638: Level: developer
640: .seealso: NEPSetWhichEigenpairs()
641: @*/
642: PetscErrorCode NEPSortEigenvalues(NEP nep,PetscInt n,PetscScalar *eig,PetscInt *perm)
643: {
645: PetscInt i,j,result,tmp;
651: for (i=0;i<n;i++) perm[i] = i;
652: /* insertion sort */
653: for (i=n-1;i>=0;i--) {
654: j = i + 1;
655: while (j<n) {
656: NEPCompareEigenvalues(nep,eig[perm[i]],eig[perm[j]],&result);
657: if (result < 0) break;
658: tmp = perm[j-1]; perm[j-1] = perm[j]; perm[j] = tmp;
659: j++;
660: }
661: }
662: return(0);
663: }
667: /*@
668: NEPCompareEigenvalues - Compares two eigenvalues according to a certain criterion.
670: Not Collective
672: Input Parameters:
673: + nep - the nonlinear eigensolver context
674: . a - the 1st eigenvalue
675: - b - the 2nd eigenvalue
677: Output Parameter:
678: . res - result of comparison
680: Notes:
681: Returns an integer less than, equal to, or greater than zero if the first
682: eigenvalue is considered to be respectively less than, equal to, or greater
683: than the second one.
685: The criterion of comparison is related to the 'which' parameter set with
686: NEPSetWhichEigenpairs().
688: Level: developer
690: .seealso: NEPSortEigenvalues(), NEPSetWhichEigenpairs()
691: @*/
692: PetscErrorCode NEPCompareEigenvalues(NEP nep,PetscScalar a,PetscScalar b,PetscInt *result)
693: {
699: if (!nep->comparison) SETERRQ(PETSC_COMM_SELF,1,"Undefined eigenvalue comparison function");
700: (*nep->comparison)(a,0.0,b,0.0,result,nep->comparisonctx);
701: return(0);
702: }
706: /*@
707: NEPGetOperationCounters - Gets the total number of function evaluations, dot
708: products, and linear solve iterations used by the NEP object during the last
709: NEPSolve() call.
711: Not Collective
713: Input Parameter:
714: . nep - nonlinear eigensolver context
716: Output Parameter:
717: + nfuncs - number of function evaluations
718: . dots - number of dot product operations
719: - lits - number of linear iterations
721: Notes:
722: These counters are reset to zero at each successive call to NEPSolve().
724: Level: intermediate
726: @*/
727: PetscErrorCode NEPGetOperationCounters(NEP nep,PetscInt* nfuncs,PetscInt* dots,PetscInt* lits)
728: {
733: if (nfuncs) *nfuncs = nep->nfuncs;
734: if (dots) {
735: if (!nep->ip) { NEPGetIP(nep,&nep->ip); }
736: IPGetOperationCounters(nep->ip,dots);
737: }
738: if (lits) *lits = nep->linits;
739: return(0);
740: }
744: /*@
745: NEPComputeFunction - Computes the function matrix T(lambda) that has been
746: set with NEPSetFunction().
748: Collective on NEP and Mat
750: Input Parameters:
751: + nep - the NEP context
752: - lambda - the scalar argument
754: Output Parameters:
755: + A - Function matrix
756: . B - optional preconditioning matrix
757: - flg - flag indicating matrix structure (see MatStructure enum)
759: Notes:
760: NEPComputeFunction() is typically used within nonlinear eigensolvers
761: implementations, so most users would not generally call this routine
762: themselves.
764: Level: developer
766: .seealso: NEPSetFunction(), NEPGetFunction()
767: @*/
768: PetscErrorCode NEPComputeFunction(NEP nep,PetscScalar lambda,Mat *A,Mat *B,MatStructure *flg)
769: {
771: PetscInt i;
772: PetscScalar alpha;
778: if (nep->split) {
780: MatZeroEntries(*A);
781: for (i=0;i<nep->nt;i++) {
782: FNEvaluateFunction(nep->f[i],lambda,&alpha);
783: MatAXPY(*A,alpha,nep->A[i],nep->mstr);
784: }
785: if (*A != *B) SETERRQ(PetscObjectComm((PetscObject)nep),1,"Not implemented");
787: } else {
789: if (!nep->computefunction) SETERRQ(PetscObjectComm((PetscObject)nep),PETSC_ERR_USER,"Must call NEPSetFunction() first");
791: *flg = DIFFERENT_NONZERO_PATTERN;
792: PetscLogEventBegin(NEP_FunctionEval,nep,*A,*B,0);
794: PetscStackPush("NEP user Function function");
795: (*nep->computefunction)(nep,lambda,A,B,flg,nep->functionctx);
796: PetscStackPop;
798: PetscLogEventEnd(NEP_FunctionEval,nep,*A,*B,0);
799: nep->nfuncs++;
801: }
802: return(0);
803: }
807: /*@
808: NEPComputeJacobian - Computes the Jacobian matrix T'(lambda) that has been
809: set with NEPSetJacobian().
811: Collective on NEP and Mat
813: Input Parameters:
814: + nep - the NEP context
815: - lambda - the scalar argument
817: Output Parameters:
818: + A - Jacobian matrix
819: - flg - flag indicating matrix structure (see MatStructure enum)
821: Notes:
822: Most users should not need to explicitly call this routine, as it
823: is used internally within the nonlinear eigensolvers.
825: Level: developer
827: .seealso: NEPSetJacobian(), NEPGetJacobian()
828: @*/
829: PetscErrorCode NEPComputeJacobian(NEP nep,PetscScalar lambda,Mat *A,MatStructure *flg)
830: {
832: PetscInt i;
833: PetscScalar alpha;
839: if (nep->split) {
841: MatZeroEntries(*A);
842: for (i=0;i<nep->nt;i++) {
843: FNEvaluateDerivative(nep->f[i],lambda,&alpha);
844: MatAXPY(*A,alpha,nep->A[i],nep->mstr);
845: }
847: } else {
849: if (!nep->computejacobian) SETERRQ(PetscObjectComm((PetscObject)nep),PETSC_ERR_USER,"Must call NEPSetJacobian() first");
851: *flg = DIFFERENT_NONZERO_PATTERN;
852: PetscLogEventBegin(NEP_JacobianEval,nep,*A,0,0);
854: PetscStackPush("NEP user Jacobian function");
855: (*nep->computejacobian)(nep,lambda,A,flg,nep->jacobianctx);
856: PetscStackPop;
858: PetscLogEventEnd(NEP_JacobianEval,nep,*A,0,0);
860: }
861: return(0);
862: }