Date: 2013-09-02T10:07:57+00:00

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: }