Date: 2017-05-17T08:27:18+00:00

Actual source code: nepsolve.c
slepc-3.7.4 2017-05-17
Report Typos and Errors

      1: /*
      2:       NEP 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/nepimpl.h>       /*I "slepcnep.h" I*/
     25: #include <petscdraw.h>

     29: PetscErrorCode NEPComputeVectors(NEP nep)
     30: {

     34:   NEPCheckSolved(nep,1);
     35:   switch (nep->state) {
     36:   case NEP_STATE_SOLVED:
     37:     if (nep->ops->computevectors) {
     38:       (*nep->ops->computevectors)(nep);
     39:     }
     40:     break;
     41:   default:
     42:     break;
     43:   }
     44:   nep->state = NEP_STATE_EIGENVECTORS;
     45:   return(0);
     46: }

     50: /*@
     51:    NEPSolve - Solves the nonlinear eigensystem.

     53:    Collective on NEP

     55:    Input Parameter:
     56: .  nep - eigensolver context obtained from NEPCreate()

     58:    Options Database Keys:
     59: +  -nep_view - print information about the solver used
     60: .  -nep_view_vectors binary - save the computed eigenvectors to the default binary viewer
     61: .  -nep_view_values - print computed eigenvalues
     62: .  -nep_converged_reason - print reason for convergence, and number of iterations
     63: .  -nep_error_absolute - print absolute errors of each eigenpair
     64: -  -nep_error_relative - print relative errors of each eigenpair

     66:    Level: beginner

     68: .seealso: NEPCreate(), NEPSetUp(), NEPDestroy(), NEPSetTolerances()
     69: @*/
     70: PetscErrorCode NEPSolve(NEP nep)
     71: {
     73:   PetscInt       i;

     77:   if (nep->state>=NEP_STATE_SOLVED) return(0);
     78:   PetscLogEventBegin(NEP_Solve,nep,0,0,0);

     80:   /* call setup */
     81:   NEPSetUp(nep);
     82:   nep->nconv = 0;
     83:   nep->its = 0;
     84:   for (i=0;i<nep->ncv;i++) {
     85:     nep->eigr[i]   = 0.0;
     86:     nep->eigi[i]   = 0.0;
     87:     nep->errest[i] = 0.0;
     88:     nep->perm[i]   = i;
     89:   }
     90:   NEPViewFromOptions(nep,NULL,"-nep_view_pre");

     92:   (*nep->ops->solve)(nep);
     93:   nep->state = NEP_STATE_SOLVED;

     95:   if (!nep->reason) SETERRQ(PetscObjectComm((PetscObject)nep),PETSC_ERR_PLIB,"Internal error, solver returned without setting converged reason");

     97:   if (nep->refine==NEP_REFINE_SIMPLE && nep->rits>0 && nep->nconv>0) {
     98:     NEPComputeVectors(nep);
     99:     NEPNewtonRefinementSimple(nep,&nep->rits,nep->rtol,nep->nconv);
    100:     nep->state = NEP_STATE_EIGENVECTORS;
    101:   }

    103:   /* sort eigenvalues according to nep->which parameter */
    104:   SlepcSortEigenvalues(nep->sc,nep->nconv,nep->eigr,nep->eigi,nep->perm);
    105:   PetscLogEventEnd(NEP_Solve,nep,0,0,0);

    107:   /* various viewers */
    108:   NEPViewFromOptions(nep,NULL,"-nep_view");
    109:   NEPReasonViewFromOptions(nep);
    110:   NEPErrorViewFromOptions(nep);
    111:   NEPValuesViewFromOptions(nep);
    112:   NEPVectorsViewFromOptions(nep);

    114:   /* Remove the initial subspace */
    115:   nep->nini = 0;
    116:   return(0);
    117: }

    121: /*@
    122:    NEPProjectOperator - Computes the projection of the nonlinear operator.

    124:    Collective on NEP

    126:    Input Parameters:
    127: +  nep - the nonlinear eigensolver context
    128: .  j0  - initial index
    129: -  j1  - final index

    131:    Notes:
    132:    This is available for split operator only.

    134:    The nonlinear operator T(lambda) is projected onto span(V), where V is
    135:    an orthonormal basis built internally by the solver. The projected
    136:    operator is equal to sum_i V'*A_i*V*f_i(lambda), so this function
    137:    computes all matrices Ei = V'*A_i*V, and stores them in the extra
    138:    matrices inside DS. Only rows/columns in the range [j0,j1-1] are computed,
    139:    the previous ones are assumed to be available already.

    141:    Level: developer

    143: .seealso: NEPSetSplitOperator()
    144: @*/
    145: PetscErrorCode NEPProjectOperator(NEP nep,PetscInt j0,PetscInt j1)
    146: {
    148:   PetscInt       k;
    149:   Mat            G;

    155:   NEPCheckProblem(nep,1);
    156:   NEPCheckSplit(nep,1);
    157:   BVSetActiveColumns(nep->V,j0,j1);
    158:   for (k=0;k<nep->nt;k++) {
    159:     DSGetMat(nep->ds,DSMatExtra[k],&G);
    160:     BVMatProject(nep->V,nep->A[k],nep->V,G);
    161:     DSRestoreMat(nep->ds,DSMatExtra[k],&G);
    162:   }
    163:   return(0);
    164: }

    168: /*@
    169:    NEPApplyFunction - Applies the nonlinear function T(lambda) to a given vector.

    171:    Collective on NEP

    173:    Input Parameters:
    174: +  nep    - the nonlinear eigensolver context
    175: .  lambda - scalar argument
    176: .  x      - vector to be multiplied against
    177: -  v      - workspace vector (used only in the case of split form)

    179:    Output Parameters:
    180: +  y   - result vector
    181: .  A   - Function matrix
    182: -  B   - optional preconditioning matrix

    184:    Note:
    185:    If the nonlinear operator is represented in split form, the result
    186:    y = T(lambda)*x is computed without building T(lambda) explicitly. In
    187:    that case, parameters A and B are not used. Otherwise, the matrix
    188:    T(lambda) is built and the effect is the same as a call to
    189:    NEPComputeFunction() followed by a MatMult().

    191:    Level: developer

    193: .seealso: NEPSetSplitOperator(), NEPComputeFunction()
    194: @*/
    195: PetscErrorCode NEPApplyFunction(NEP nep,PetscScalar lambda,Vec x,Vec v,Vec y,Mat A,Mat B)
    196: {
    198:   PetscInt       i;
    199:   PetscScalar    alpha;

    210:   if (nep->fui==NEP_USER_INTERFACE_SPLIT) {
    211:     VecSet(y,0.0);
    212:     for (i=0;i<nep->nt;i++) {
    213:       FNEvaluateFunction(nep->f[i],lambda,&alpha);
    214:       MatMult(nep->A[i],x,v);
    215:       VecAXPY(y,alpha,v);
    216:     }
    217:   } else {
    218:     NEPComputeFunction(nep,lambda,A,B);
    219:     MatMult(A,x,y);
    220:   }
    221:   return(0);
    222: }

    226: /*@
    227:    NEPApplyJacobian - Applies the nonlinear Jacobian T'(lambda) to a given vector.

    229:    Collective on NEP

    231:    Input Parameters:
    232: +  nep    - the nonlinear eigensolver context
    233: .  lambda - scalar argument
    234: .  x      - vector to be multiplied against
    235: -  v      - workspace vector (used only in the case of split form)

    237:    Output Parameters:
    238: +  y   - result vector
    239: -  A   - Jacobian matrix

    241:    Note:
    242:    If the nonlinear operator is represented in split form, the result
    243:    y = T'(lambda)*x is computed without building T'(lambda) explicitly. In
    244:    that case, parameter A is not used. Otherwise, the matrix
    245:    T'(lambda) is built and the effect is the same as a call to
    246:    NEPComputeJacobian() followed by a MatMult().

    248:    Level: developer

    250: .seealso: NEPSetSplitOperator(), NEPComputeJacobian()
    251: @*/
    252: PetscErrorCode NEPApplyJacobian(NEP nep,PetscScalar lambda,Vec x,Vec v,Vec y,Mat A)
    253: {
    255:   PetscInt       i;
    256:   PetscScalar    alpha;

    266:   if (nep->fui==NEP_USER_INTERFACE_SPLIT) {
    267:     VecSet(y,0.0);
    268:     for (i=0;i<nep->nt;i++) {
    269:       FNEvaluateDerivative(nep->f[i],lambda,&alpha);
    270:       MatMult(nep->A[i],x,v);
    271:       VecAXPY(y,alpha,v);
    272:     }
    273:   } else {
    274:     NEPComputeJacobian(nep,lambda,A);
    275:     MatMult(A,x,y);
    276:   }
    277:   return(0);
    278: }

    282: /*@
    283:    NEPGetIterationNumber - Gets the current iteration number. If the
    284:    call to NEPSolve() is complete, then it returns the number of iterations
    285:    carried out by the solution method.

    287:    Not Collective

    289:    Input Parameter:
    290: .  nep - the nonlinear eigensolver context

    292:    Output Parameter:
    293: .  its - number of iterations

    295:    Level: intermediate

    297:    Note:
    298:    During the i-th iteration this call returns i-1. If NEPSolve() is
    299:    complete, then parameter "its" contains either the iteration number at
    300:    which convergence was successfully reached, or failure was detected.
    301:    Call NEPGetConvergedReason() to determine if the solver converged or
    302:    failed and why.

    304: .seealso: NEPGetConvergedReason(), NEPSetTolerances()
    305: @*/
    306: PetscErrorCode NEPGetIterationNumber(NEP nep,PetscInt *its)
    307: {
    311:   *its = nep->its;
    312:   return(0);
    313: }

    317: /*@
    318:    NEPGetConverged - Gets the number of converged eigenpairs.

    320:    Not Collective

    322:    Input Parameter:
    323: .  nep - the nonlinear eigensolver context

    325:    Output Parameter:
    326: .  nconv - number of converged eigenpairs

    328:    Note:
    329:    This function should be called after NEPSolve() has finished.

    331:    Level: beginner

    333: .seealso: NEPSetDimensions(), NEPSolve()
    334: @*/
    335: PetscErrorCode NEPGetConverged(NEP nep,PetscInt *nconv)
    336: {
    340:   NEPCheckSolved(nep,1);
    341:   *nconv = nep->nconv;
    342:   return(0);
    343: }

    347: /*@
    348:    NEPGetConvergedReason - Gets the reason why the NEPSolve() iteration was
    349:    stopped.

    351:    Not Collective

    353:    Input Parameter:
    354: .  nep - the nonlinear eigensolver context

    356:    Output Parameter:
    357: .  reason - negative value indicates diverged, positive value converged

    359:    Notes:

    361:    Possible values for reason are
    362: +  NEP_CONVERGED_TOL - converged up to tolerance
    363: .  NEP_CONVERGED_USER - converged due to a user-defined condition
    364: .  NEP_DIVERGED_ITS - required more than max_it iterations to reach convergence
    365: .  NEP_DIVERGED_BREAKDOWN - generic breakdown in method
    366: -  NEP_DIVERGED_LINEAR_SOLVE - inner linear solve failed

    368:    Can only be called after the call to NEPSolve() is complete.

    370:    Level: intermediate

    372: .seealso: NEPSetTolerances(), NEPSolve(), NEPConvergedReason
    373: @*/
    374: PetscErrorCode NEPGetConvergedReason(NEP nep,NEPConvergedReason *reason)
    375: {
    379:   NEPCheckSolved(nep,1);
    380:   *reason = nep->reason;
    381:   return(0);
    382: }

    386: /*@
    387:    NEPGetEigenpair - Gets the i-th solution of the eigenproblem as computed by
    388:    NEPSolve(). The solution consists in both the eigenvalue and the eigenvector.

    390:    Logically Collective on NEP

    392:    Input Parameters:
    393: +  nep - nonlinear eigensolver context
    394: -  i   - index of the solution

    396:    Output Parameters:
    397: +  eigr - real part of eigenvalue
    398: .  eigi - imaginary part of eigenvalue
    399: .  Vr   - real part of eigenvector
    400: -  Vi   - imaginary part of eigenvector

    402:    Notes:
    403:    It is allowed to pass NULL for Vr and Vi, if the eigenvector is not
    404:    required. Otherwise, the caller must provide valid Vec objects, i.e.,
    405:    they must be created by the calling program with e.g. MatCreateVecs().

    407:    If the eigenvalue is real, then eigi and Vi are set to zero. If PETSc is
    408:    configured with complex scalars the eigenvalue is stored
    409:    directly in eigr (eigi is set to zero) and the eigenvector in Vr (Vi is
    410:    set to zero). In both cases, the user can pass NULL in eigi and Vi.

    412:    The index i should be a value between 0 and nconv-1 (see NEPGetConverged()).
    413:    Eigenpairs are indexed according to the ordering criterion established
    414:    with NEPSetWhichEigenpairs().

    416:    Level: beginner

    418: .seealso: NEPSolve(), NEPGetConverged(), NEPSetWhichEigenpairs()
    419: @*/
    420: PetscErrorCode NEPGetEigenpair(NEP nep,PetscInt i,PetscScalar *eigr,PetscScalar *eigi,Vec Vr,Vec Vi)
    421: {
    422:   PetscInt       k;

    430:   NEPCheckSolved(nep,1);
    431:   if (i<0 || i>=nep->nconv) SETERRQ(PetscObjectComm((PetscObject)nep),PETSC_ERR_ARG_OUTOFRANGE,"Argument 2 out of range");

    433:   NEPComputeVectors(nep);
    434:   k = nep->perm[i];

    436:   /* eigenvalue */
    437: #if defined(PETSC_USE_COMPLEX)
    438:   if (eigr) *eigr = nep->eigr[k];
    439:   if (eigi) *eigi = 0;
    440: #else
    441:   if (eigr) *eigr = nep->eigr[k];
    442:   if (eigi) *eigi = nep->eigi[k];
    443: #endif

    445:   /* eigenvector */
    446: #if defined(PETSC_USE_COMPLEX)
    447:   if (Vr) { BVCopyVec(nep->V,k,Vr); }
    448:   if (Vi) { VecSet(Vi,0.0); }
    449: #else
    450:   if (nep->eigi[k]>0) { /* first value of conjugate pair */
    451:     if (Vr) { BVCopyVec(nep->V,k,Vr); }
    452:     if (Vi) { BVCopyVec(nep->V,k+1,Vi); }
    453:   } else if (nep->eigi[k]<0) { /* second value of conjugate pair */
    454:     if (Vr) { BVCopyVec(nep->V,k-1,Vr); }
    455:     if (Vi) {
    456:       BVCopyVec(nep->V,k,Vi);
    457:       VecScale(Vi,-1.0);
    458:     }
    459:   } else { /* real eigenvalue */
    460:     if (Vr) { BVCopyVec(nep->V,k,Vr); }
    461:     if (Vi) { VecSet(Vi,0.0); }
    462:   }
    463: #endif
    464:   return(0);
    465: }

    469: /*@
    470:    NEPGetErrorEstimate - Returns the error estimate associated to the i-th
    471:    computed eigenpair.

    473:    Not Collective

    475:    Input Parameter:
    476: +  nep - nonlinear eigensolver context
    477: -  i   - index of eigenpair

    479:    Output Parameter:
    480: .  errest - the error estimate

    482:    Notes:
    483:    This is the error estimate used internally by the eigensolver. The actual
    484:    error bound can be computed with NEPComputeRelativeError().

    486:    Level: advanced

    488: .seealso: NEPComputeRelativeError()
    489: @*/
    490: PetscErrorCode NEPGetErrorEstimate(NEP nep,PetscInt i,PetscReal *errest)
    491: {
    495:   NEPCheckSolved(nep,1);
    496:   if (i<0 || i>=nep->nconv) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_OUTOFRANGE,"Argument 2 out of range");
    497:   if (errest) *errest = nep->errest[nep->perm[i]];
    498:   return(0);
    499: }

    503: /*
    504:    NEPComputeResidualNorm_Private - Computes the norm of the residual vector
    505:    associated with an eigenpair.

    507:    Input Parameters:
    508:      lambda - eigenvalue
    509:      x      - eigenvector
    510:      w      - array of work vectors (two vectors in split form, one vector otherwise)
    511: */
    512: PetscErrorCode NEPComputeResidualNorm_Private(NEP nep,PetscScalar lambda,Vec x,Vec *w,PetscReal *norm)
    513: {
    515:   Vec            y,z=NULL;

    518:   y = w[0];
    519:   if (nep->fui==NEP_USER_INTERFACE_SPLIT) z = w[1];
    520:   NEPApplyFunction(nep,lambda,x,z,y,nep->function,nep->function_pre);
    521:   VecNorm(y,NORM_2,norm);
    522:   return(0);
    523: }

    527: /*@
    528:    NEPComputeError - Computes the error (based on the residual norm) associated
    529:    with the i-th computed eigenpair.

    531:    Collective on NEP

    533:    Input Parameter:
    534: +  nep  - the nonlinear eigensolver context
    535: .  i    - the solution index
    536: -  type - the type of error to compute

    538:    Output Parameter:
    539: .  error - the error

    541:    Notes:
    542:    The error can be computed in various ways, all of them based on the residual
    543:    norm computed as ||T(lambda)x||_2 where lambda is the eigenvalue and x is the
    544:    eigenvector.

    546:    Level: beginner

    548: .seealso: NEPErrorType, NEPSolve(), NEPGetErrorEstimate()
    549: @*/
    550: PetscErrorCode NEPComputeError(NEP nep,PetscInt i,NEPErrorType type,PetscReal *error)
    551: {
    553:   Vec            xr,xi=NULL;
    554:   PetscInt       j,nwork,issplit=0;
    555:   PetscScalar    kr,ki,s;
    556:   PetscReal      er,z=0.0;
    557:   PetscBool      flg;

    564:   NEPCheckSolved(nep,1);

    566:   /* allocate work vectors */
    567: #if defined(PETSC_USE_COMPLEX)
    568:   nwork = 2;
    569: #else
    570:   nwork = 3;
    571: #endif
    572:   if (nep->fui==NEP_USER_INTERFACE_SPLIT) {
    573:     issplit = 1;
    574:     nwork++;  /* need an extra work vector for NEPComputeResidualNorm_Private */
    575:   }
    576:   NEPSetWorkVecs(nep,nwork);
    577:   xr = nep->work[issplit+1];
    578: #if !defined(PETSC_USE_COMPLEX)
    579:   xi = nep->work[issplit+2];
    580: #endif

    582:   /* compute residual norms */
    583:   NEPGetEigenpair(nep,i,&kr,&ki,xr,xi);
    584: #if !defined(PETSC_USE_COMPLEX)
    585:   if (ki) SETERRQ(PETSC_COMM_SELF,1,"Not implemented for complex eigenvalues with real scalars");
    586: #endif
    587:   NEPComputeResidualNorm_Private(nep,kr,xr,nep->work,error);
    588:   VecNorm(xr,NORM_2,&er);

    590:   /* compute error */
    591:   switch (type) {
    592:     case NEP_ERROR_ABSOLUTE:
    593:       break;
    594:     case NEP_ERROR_RELATIVE:
    595:       *error /= PetscAbsScalar(kr)*er;
    596:       break;
    597:     case NEP_ERROR_BACKWARD:
    598:       if (nep->fui!=NEP_USER_INTERFACE_SPLIT) {
    599:         *error = 0.0;
    600:         PetscInfo(nep,"Backward error only available in split form\n");
    601:         break;
    602:       }
    603:       /* initialization of matrix norms */
    604:       if (!nep->nrma[0]) {
    605:         for (j=0;j<nep->nt;j++) {
    606:           MatHasOperation(nep->A[j],MATOP_NORM,&flg);
    607:           if (!flg) SETERRQ(PetscObjectComm((PetscObject)nep),PETSC_ERR_ARG_WRONG,"The computation of backward errors requires a matrix norm operation");
    608:           MatNorm(nep->A[j],NORM_INFINITY,&nep->nrma[j]);
    609:         }
    610:       }
    611:       for (j=0;j<nep->nt;j++) {
    612:         FNEvaluateFunction(nep->f[j],kr,&s);
    613:         z = z + nep->nrma[j]*PetscAbsScalar(s);
    614:       }
    615:       *error /= z;
    616:       break;
    617:     default:
    618:       SETERRQ(PetscObjectComm((PetscObject)nep),PETSC_ERR_ARG_OUTOFRANGE,"Invalid error type");
    619:   }
    620:   return(0);
    621: }

    625: /*@
    626:    NEPComputeFunction - Computes the function matrix T(lambda) that has been
    627:    set with NEPSetFunction().

    629:    Collective on NEP and Mat

    631:    Input Parameters:
    632: +  nep    - the NEP context
    633: -  lambda - the scalar argument

    635:    Output Parameters:
    636: +  A   - Function matrix
    637: -  B   - optional preconditioning matrix

    639:    Notes:
    640:    NEPComputeFunction() is typically used within nonlinear eigensolvers
    641:    implementations, so most users would not generally call this routine
    642:    themselves.

    644:    Level: developer

    646: .seealso: NEPSetFunction(), NEPGetFunction()
    647: @*/
    648: PetscErrorCode NEPComputeFunction(NEP nep,PetscScalar lambda,Mat A,Mat B)
    649: {
    651:   PetscInt       i;
    652:   PetscScalar    alpha;

    656:   NEPCheckProblem(nep,1);
    657:   switch (nep->fui) {
    658:   case NEP_USER_INTERFACE_CALLBACK:
    659:     if (!nep->computefunction) SETERRQ(PetscObjectComm((PetscObject)nep),PETSC_ERR_USER,"Must call NEPSetFunction() first");
    660:     PetscLogEventBegin(NEP_FunctionEval,nep,A,B,0);
    661:     PetscStackPush("NEP user Function function");
    662:     (*nep->computefunction)(nep,lambda,A,B,nep->functionctx);
    663:     PetscStackPop;
    664:     PetscLogEventEnd(NEP_FunctionEval,nep,A,B,0);
    665:     break;
    666:   case NEP_USER_INTERFACE_SPLIT:
    667:     MatZeroEntries(A);
    668:     for (i=0;i<nep->nt;i++) {
    669:       FNEvaluateFunction(nep->f[i],lambda,&alpha);
    670:       MatAXPY(A,alpha,nep->A[i],nep->mstr);
    671:     }
    672:     if (A != B) SETERRQ(PetscObjectComm((PetscObject)nep),1,"Not implemented");
    673:     break;
    674:   case NEP_USER_INTERFACE_DERIVATIVES:
    675:     PetscLogEventBegin(NEP_DerivativesEval,nep,A,B,0);
    676:     PetscStackPush("NEP user Derivatives function");
    677:     (*nep->computederivatives)(nep,lambda,0,A,nep->derivativesctx);
    678:     PetscStackPop;
    679:     PetscLogEventEnd(NEP_DerivativesEval,nep,A,B,0);
    680:     break;
    681:   }
    682:   return(0);
    683: }

    687: /*@
    688:    NEPComputeJacobian - Computes the Jacobian matrix T'(lambda) that has been
    689:    set with NEPSetJacobian().

    691:    Collective on NEP and Mat

    693:    Input Parameters:
    694: +  nep    - the NEP context
    695: -  lambda - the scalar argument

    697:    Output Parameters:
    698: .  A   - Jacobian matrix

    700:    Notes:
    701:    Most users should not need to explicitly call this routine, as it
    702:    is used internally within the nonlinear eigensolvers.

    704:    Level: developer

    706: .seealso: NEPSetJacobian(), NEPGetJacobian()
    707: @*/
    708: PetscErrorCode NEPComputeJacobian(NEP nep,PetscScalar lambda,Mat A)
    709: {
    711:   PetscInt       i;
    712:   PetscScalar    alpha;

    716:   NEPCheckProblem(nep,1);
    717:   switch (nep->fui) {
    718:   case NEP_USER_INTERFACE_CALLBACK:
    719:     if (!nep->computejacobian) SETERRQ(PetscObjectComm((PetscObject)nep),PETSC_ERR_USER,"Must call NEPSetJacobian() first");
    720:     PetscLogEventBegin(NEP_JacobianEval,nep,A,0,0);
    721:     PetscStackPush("NEP user Jacobian function");
    722:     (*nep->computejacobian)(nep,lambda,A,nep->jacobianctx);
    723:     PetscStackPop;
    724:     PetscLogEventEnd(NEP_JacobianEval,nep,A,0,0);
    725:     break;
    726:   case NEP_USER_INTERFACE_SPLIT:
    727:     MatZeroEntries(A);
    728:     for (i=0;i<nep->nt;i++) {
    729:       FNEvaluateDerivative(nep->f[i],lambda,&alpha);
    730:       MatAXPY(A,alpha,nep->A[i],nep->mstr);
    731:     }
    732:     break;
    733:   case NEP_USER_INTERFACE_DERIVATIVES:
    734:     PetscLogEventBegin(NEP_DerivativesEval,nep,A,0,0);
    735:     PetscStackPush("NEP user Derivatives function");
    736:     (*nep->computederivatives)(nep,lambda,1,A,nep->derivativesctx);
    737:     PetscStackPop;
    738:     PetscLogEventEnd(NEP_DerivativesEval,nep,A,0,0);
    739:     break;
    740:   }
    741:   return(0);
    742: }