Date: 2021-09-20T09:44:08+00:00

Actual source code: nepsolve.c
slepc-3.15.2 2021-09-20
Report Typos and Errors

      1: /*
      2:    - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
      3:    SLEPc - Scalable Library for Eigenvalue Problem Computations
      4:    Copyright (c) 2002-2021, Universitat Politecnica de Valencia, Spain

      6:    This file is part of SLEPc.
      7:    SLEPc is distributed under a 2-clause BSD license (see LICENSE).
      8:    - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
      9: */
     10: /*
     11:    NEP routines related to the solution process

     13:    References:

     15:        [1] C. Campos and J.E. Roman, "NEP: a module for the parallel solution
     16:            of nonlinear eigenvalue problems in SLEPc", ACM Trans. Math. Soft.
     17:            (to appear), arXiv:1910.11712, 2021.
     18: */

     20: #include <slepc/private/nepimpl.h>
     21: #include <slepc/private/bvimpl.h>
     22: #include <petscdraw.h>

     24: static PetscBool  cited = PETSC_FALSE;
     25: static const char citation[] =
     26:   "@Article{slepc-nep,\n"
     27:   "   author = \"C. Campos and J. E. Roman\",\n"
     28:   "   title = \"{NEP}: a module for the parallel solution of nonlinear eigenvalue problems in {SLEPc}\",\n"
     29:   "   journal = \"{ACM} Trans. Math. Software\",\n"
     30:   "   note = \"To appear\",\n"
     31:   "   url = \"https://arxiv.org/abs/1910.11712\",\n"
     32:   "   year = \"2021\"\n"
     33:   "}\n";

     35: PetscErrorCode NEPComputeVectors(NEP nep)
     36: {

     40:   NEPCheckSolved(nep,1);
     41:   if (nep->state==NEP_STATE_SOLVED && nep->ops->computevectors) {
     42:     (*nep->ops->computevectors)(nep);
     43:   }
     44:   nep->state = NEP_STATE_EIGENVECTORS;
     45:   return(0);
     46: }

     48: /*@
     49:    NEPSolve - Solves the nonlinear eigensystem.

     51:    Collective on nep

     53:    Input Parameter:
     54: .  nep - eigensolver context obtained from NEPCreate()

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

     64:    Level: beginner

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

     75:   if (nep->state>=NEP_STATE_SOLVED) return(0);
     76:   PetscCitationsRegister(citation,&cited);
     77:   PetscLogEventBegin(NEP_Solve,nep,0,0,0);

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

     92:   /* call solver */
     93:   (*nep->ops->solve)(nep);
     94:   if (!nep->reason) SETERRQ(PetscObjectComm((PetscObject)nep),PETSC_ERR_PLIB,"Internal error, solver returned without setting converged reason");
     95:   nep->state = NEP_STATE_SOLVED;

     97:   /* Only the first nconv columns contain useful information */
     98:   BVSetActiveColumns(nep->V,0,nep->nconv);
     99:   if (nep->twosided) { BVSetActiveColumns(nep->W,0,nep->nconv); }

    101:   if (nep->refine==NEP_REFINE_SIMPLE && nep->rits>0 && nep->nconv>0) {
    102:     NEPComputeVectors(nep);
    103:     NEPNewtonRefinementSimple(nep,&nep->rits,nep->rtol,nep->nconv);
    104:     nep->state = NEP_STATE_EIGENVECTORS;
    105:   }

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

    111:   /* various viewers */
    112:   NEPViewFromOptions(nep,NULL,"-nep_view");
    113:   NEPConvergedReasonViewFromOptions(nep);
    114:   NEPErrorViewFromOptions(nep);
    115:   NEPValuesViewFromOptions(nep);
    116:   NEPVectorsViewFromOptions(nep);

    118:   /* Remove the initial subspace */
    119:   nep->nini = 0;

    121:   /* Reset resolvent information */
    122:   MatDestroy(&nep->resolvent);
    123:   return(0);
    124: }

    126: /*@
    127:    NEPProjectOperator - Computes the projection of the nonlinear operator.

    129:    Collective on nep

    131:    Input Parameters:
    132: +  nep - the nonlinear eigensolver context
    133: .  j0  - initial index
    134: -  j1  - final index

    136:    Notes:
    137:    This is available for split operator only.

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

    146:    Level: developer

    148: .seealso: NEPSetSplitOperator()
    149: @*/
    150: PetscErrorCode NEPProjectOperator(NEP nep,PetscInt j0,PetscInt j1)
    151: {
    153:   PetscInt       k;
    154:   Mat            G;

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

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

    174:    Collective on nep

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

    182:    Output Parameters:
    183: +  y   - result vector
    184: .  A   - Function matrix
    185: -  B   - optional preconditioning matrix

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

    194:    Level: developer

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

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

    227: /*@
    228:    NEPApplyAdjoint - Applies the adjoint nonlinear function T(lambda)^* to a given vector.

    230:    Collective on nep

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

    238:    Output Parameters:
    239: +  y   - result vector
    240: .  A   - Function matrix
    241: -  B   - optional preconditioning matrix

    243:    Level: developer

    245: .seealso: NEPSetSplitOperator(), NEPComputeFunction(), NEPApplyFunction()
    246: @*/
    247: PetscErrorCode NEPApplyAdjoint(NEP nep,PetscScalar lambda,Vec x,Vec v,Vec y,Mat A,Mat B)
    248: {
    250:   PetscInt       i;
    251:   PetscScalar    alpha;

    262:   VecConjugate(x);
    263:   if (nep->fui==NEP_USER_INTERFACE_SPLIT) {
    264:     VecSet(y,0.0);
    265:     for (i=0;i<nep->nt;i++) {
    266:       FNEvaluateFunction(nep->f[i],lambda,&alpha);
    267:       MatMultTranspose(nep->A[i],x,v);
    268:       VecAXPY(y,alpha,v);
    269:     }
    270:   } else {
    271:     NEPComputeFunction(nep,lambda,A,B);
    272:     MatMultTranspose(A,x,y);
    273:   }
    274:   VecConjugate(x);
    275:   VecConjugate(y);
    276:   return(0);
    277: }

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

    282:    Collective on nep

    284:    Input Parameters:
    285: +  nep    - the nonlinear eigensolver context
    286: .  lambda - scalar argument
    287: .  x      - vector to be multiplied against
    288: -  v      - workspace vector (used only in the case of split form)

    290:    Output Parameters:
    291: +  y   - result vector
    292: -  A   - Jacobian matrix

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

    301:    Level: developer

    303: .seealso: NEPSetSplitOperator(), NEPComputeJacobian()
    304: @*/
    305: PetscErrorCode NEPApplyJacobian(NEP nep,PetscScalar lambda,Vec x,Vec v,Vec y,Mat A)
    306: {
    308:   PetscInt       i;
    309:   PetscScalar    alpha;

    319:   if (nep->fui==NEP_USER_INTERFACE_SPLIT) {
    320:     VecSet(y,0.0);
    321:     for (i=0;i<nep->nt;i++) {
    322:       FNEvaluateDerivative(nep->f[i],lambda,&alpha);
    323:       MatMult(nep->A[i],x,v);
    324:       VecAXPY(y,alpha,v);
    325:     }
    326:   } else {
    327:     NEPComputeJacobian(nep,lambda,A);
    328:     MatMult(A,x,y);
    329:   }
    330:   return(0);
    331: }

    333: /*@
    334:    NEPGetIterationNumber - Gets the current iteration number. If the
    335:    call to NEPSolve() is complete, then it returns the number of iterations
    336:    carried out by the solution method.

    338:    Not Collective

    340:    Input Parameter:
    341: .  nep - the nonlinear eigensolver context

    343:    Output Parameter:
    344: .  its - number of iterations

    346:    Note:
    347:    During the i-th iteration this call returns i-1. If NEPSolve() is
    348:    complete, then parameter "its" contains either the iteration number at
    349:    which convergence was successfully reached, or failure was detected.
    350:    Call NEPGetConvergedReason() to determine if the solver converged or
    351:    failed and why.

    353:    Level: intermediate

    355: .seealso: NEPGetConvergedReason(), NEPSetTolerances()
    356: @*/
    357: PetscErrorCode NEPGetIterationNumber(NEP nep,PetscInt *its)
    358: {
    362:   *its = nep->its;
    363:   return(0);
    364: }

    366: /*@
    367:    NEPGetConverged - Gets the number of converged eigenpairs.

    369:    Not Collective

    371:    Input Parameter:
    372: .  nep - the nonlinear eigensolver context

    374:    Output Parameter:
    375: .  nconv - number of converged eigenpairs

    377:    Note:
    378:    This function should be called after NEPSolve() has finished.

    380:    Level: beginner

    382: .seealso: NEPSetDimensions(), NEPSolve()
    383: @*/
    384: PetscErrorCode NEPGetConverged(NEP nep,PetscInt *nconv)
    385: {
    389:   NEPCheckSolved(nep,1);
    390:   *nconv = nep->nconv;
    391:   return(0);
    392: }

    394: /*@
    395:    NEPGetConvergedReason - Gets the reason why the NEPSolve() iteration was
    396:    stopped.

    398:    Not Collective

    400:    Input Parameter:
    401: .  nep - the nonlinear eigensolver context

    403:    Output Parameter:
    404: .  reason - negative value indicates diverged, positive value converged

    406:    Notes:

    408:    Possible values for reason are
    409: +  NEP_CONVERGED_TOL - converged up to tolerance
    410: .  NEP_CONVERGED_USER - converged due to a user-defined condition
    411: .  NEP_DIVERGED_ITS - required more than max_it iterations to reach convergence
    412: .  NEP_DIVERGED_BREAKDOWN - generic breakdown in method
    413: .  NEP_DIVERGED_LINEAR_SOLVE - inner linear solve failed
    414: -  NEP_DIVERGED_SUBSPACE_EXHAUSTED - run out of space for the basis in an
    415:    unrestarted solver

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

    419:    Level: intermediate

    421: .seealso: NEPSetTolerances(), NEPSolve(), NEPConvergedReason
    422: @*/
    423: PetscErrorCode NEPGetConvergedReason(NEP nep,NEPConvergedReason *reason)
    424: {
    428:   NEPCheckSolved(nep,1);
    429:   *reason = nep->reason;
    430:   return(0);
    431: }

    433: /*@C
    434:    NEPGetEigenpair - Gets the i-th solution of the eigenproblem as computed by
    435:    NEPSolve(). The solution consists in both the eigenvalue and the eigenvector.

    437:    Logically Collective on nep

    439:    Input Parameters:
    440: +  nep - nonlinear eigensolver context
    441: -  i   - index of the solution

    443:    Output Parameters:
    444: +  eigr - real part of eigenvalue
    445: .  eigi - imaginary part of eigenvalue
    446: .  Vr   - real part of eigenvector
    447: -  Vi   - imaginary part of eigenvector

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

    454:    If the eigenvalue is real, then eigi and Vi are set to zero. If PETSc is
    455:    configured with complex scalars the eigenvalue is stored
    456:    directly in eigr (eigi is set to zero) and the eigenvector in Vr (Vi is
    457:    set to zero). In any case, the user can pass NULL in Vr or Vi if one of
    458:    them is not required.

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

    464:    Level: beginner

    466: .seealso: NEPSolve(), NEPGetConverged(), NEPSetWhichEigenpairs(), NEPGetLeftEigenvector()
    467: @*/
    468: PetscErrorCode NEPGetEigenpair(NEP nep,PetscInt i,PetscScalar *eigr,PetscScalar *eigi,Vec Vr,Vec Vi)
    469: {
    470:   PetscInt       k;

    478:   NEPCheckSolved(nep,1);
    479:   if (i<0) SETERRQ(PetscObjectComm((PetscObject)nep),PETSC_ERR_ARG_OUTOFRANGE,"The index cannot be negative");
    480:   if (i>=nep->nconv) SETERRQ(PetscObjectComm((PetscObject)nep),PETSC_ERR_ARG_OUTOFRANGE,"The index can be nconv-1 at most, see NEPGetConverged()");

    482:   NEPComputeVectors(nep);
    483:   k = nep->perm[i];

    485:   /* eigenvalue */
    486: #if defined(PETSC_USE_COMPLEX)
    487:   if (eigr) *eigr = nep->eigr[k];
    488:   if (eigi) *eigi = 0;
    489: #else
    490:   if (eigr) *eigr = nep->eigr[k];
    491:   if (eigi) *eigi = nep->eigi[k];
    492: #endif

    494:   /* eigenvector */
    495:   BV_GetEigenvector(nep->V,k,nep->eigi[k],Vr,Vi);
    496:   return(0);
    497: }

    499: /*@
    500:    NEPGetLeftEigenvector - Gets the i-th left eigenvector as computed by NEPSolve().

    502:    Logically Collective on nep

    504:    Input Parameters:
    505: +  nep - eigensolver context
    506: -  i   - index of the solution

    508:    Output Parameters:
    509: +  Wr   - real part of left eigenvector
    510: -  Wi   - imaginary part of left eigenvector

    512:    Notes:
    513:    The caller must provide valid Vec objects, i.e., they must be created
    514:    by the calling program with e.g. MatCreateVecs().

    516:    If the corresponding eigenvalue is real, then Wi is set to zero. If PETSc is
    517:    configured with complex scalars the eigenvector is stored directly in Wr
    518:    (Wi is set to zero). In any case, the user can pass NULL in Wr or Wi if one of
    519:    them is not required.

    521:    The index i should be a value between 0 and nconv-1 (see NEPGetConverged()).
    522:    Eigensolutions are indexed according to the ordering criterion established
    523:    with NEPSetWhichEigenpairs().

    525:    Left eigenvectors are available only if the twosided flag was set, see
    526:    NEPSetTwoSided().

    528:    Level: intermediate

    530: .seealso: NEPGetEigenpair(), NEPGetConverged(), NEPSetWhichEigenpairs(), NEPSetTwoSided()
    531: @*/
    532: PetscErrorCode NEPGetLeftEigenvector(NEP nep,PetscInt i,Vec Wr,Vec Wi)
    533: {
    535:   PetscInt       k;

    542:   NEPCheckSolved(nep,1);
    543:   if (!nep->twosided) SETERRQ(PetscObjectComm((PetscObject)nep),PETSC_ERR_ARG_WRONGSTATE,"Must request left vectors with NEPSetTwoSided");
    544:   if (i<0 || i>=nep->nconv) SETERRQ(PetscObjectComm((PetscObject)nep),PETSC_ERR_ARG_OUTOFRANGE,"Argument 2 out of range");
    545:   NEPComputeVectors(nep);
    546:   k = nep->perm[i];
    547:   BV_GetEigenvector(nep->W,k,nep->eigi[k],Wr,Wi);
    548:   return(0);
    549: }

    551: /*@
    552:    NEPGetErrorEstimate - Returns the error estimate associated to the i-th
    553:    computed eigenpair.

    555:    Not Collective

    557:    Input Parameter:
    558: +  nep - nonlinear eigensolver context
    559: -  i   - index of eigenpair

    561:    Output Parameter:
    562: .  errest - the error estimate

    564:    Notes:
    565:    This is the error estimate used internally by the eigensolver. The actual
    566:    error bound can be computed with NEPComputeError().

    568:    Level: advanced

    570: .seealso: NEPComputeError()
    571: @*/
    572: PetscErrorCode NEPGetErrorEstimate(NEP nep,PetscInt i,PetscReal *errest)
    573: {
    577:   NEPCheckSolved(nep,1);
    578:   if (i<0 || i>=nep->nconv) SETERRQ(PetscObjectComm((PetscObject)nep),PETSC_ERR_ARG_OUTOFRANGE,"Argument 2 out of range");
    579:   *errest = nep->errest[nep->perm[i]];
    580:   return(0);
    581: }

    583: /*
    584:    NEPComputeResidualNorm_Private - Computes the norm of the residual vector
    585:    associated with an eigenpair.

    587:    Input Parameters:
    588:      adj    - whether the adjoint T^* must be used instead of T
    589:      lambda - eigenvalue
    590:      x      - eigenvector
    591:      w      - array of work vectors (two vectors in split form, one vector otherwise)
    592: */
    593: PetscErrorCode NEPComputeResidualNorm_Private(NEP nep,PetscBool adj,PetscScalar lambda,Vec x,Vec *w,PetscReal *norm)
    594: {
    596:   Vec            y,z=NULL;

    599:   y = w[0];
    600:   if (nep->fui==NEP_USER_INTERFACE_SPLIT) z = w[1];
    601:   if (adj) {
    602:     NEPApplyAdjoint(nep,lambda,x,z,y,nep->function,nep->function_pre);
    603:   } else {
    604:     NEPApplyFunction(nep,lambda,x,z,y,nep->function,nep->function_pre);
    605:   }
    606:   VecNorm(y,NORM_2,norm);
    607:   return(0);
    608: }

    610: /*@
    611:    NEPComputeError - Computes the error (based on the residual norm) associated
    612:    with the i-th computed eigenpair.

    614:    Collective on nep

    616:    Input Parameter:
    617: +  nep  - the nonlinear eigensolver context
    618: .  i    - the solution index
    619: -  type - the type of error to compute

    621:    Output Parameter:
    622: .  error - the error

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

    629:    Level: beginner

    631: .seealso: NEPErrorType, NEPSolve(), NEPGetErrorEstimate()
    632: @*/
    633: PetscErrorCode NEPComputeError(NEP nep,PetscInt i,NEPErrorType type,PetscReal *error)
    634: {
    636:   Vec            xr,xi=NULL;
    637:   PetscInt       j,nwork,issplit=0;
    638:   PetscScalar    kr,ki,s;
    639:   PetscReal      er,z=0.0,errorl,nrm;
    640:   PetscBool      flg;

    647:   NEPCheckSolved(nep,1);

    649:   /* allocate work vectors */
    650: #if defined(PETSC_USE_COMPLEX)
    651:   nwork = 2;
    652: #else
    653:   nwork = 3;
    654: #endif
    655:   if (nep->fui==NEP_USER_INTERFACE_SPLIT) {
    656:     issplit = 1;
    657:     nwork++;  /* need an extra work vector for NEPComputeResidualNorm_Private */
    658:   }
    659:   NEPSetWorkVecs(nep,nwork);
    660:   xr = nep->work[issplit+1];
    661: #if !defined(PETSC_USE_COMPLEX)
    662:   xi = nep->work[issplit+2];
    663: #endif

    665:   /* compute residual norms */
    666:   NEPGetEigenpair(nep,i,&kr,&ki,xr,xi);
    667: #if !defined(PETSC_USE_COMPLEX)
    668:   if (ki) SETERRQ(PetscObjectComm((PetscObject)nep),1,"Not implemented for complex eigenvalues with real scalars");
    669: #endif
    670:   NEPComputeResidualNorm_Private(nep,PETSC_FALSE,kr,xr,nep->work,error);
    671:   VecNorm(xr,NORM_2,&er);

    673:   /* if two-sided, compute left residual norm and take the maximum */
    674:   if (nep->twosided) {
    675:     NEPGetLeftEigenvector(nep,i,xr,xi);
    676:     NEPComputeResidualNorm_Private(nep,PETSC_TRUE,kr,xr,nep->work,&errorl);
    677:     *error = PetscMax(*error,errorl);
    678:   }

    680:   /* compute error */
    681:   switch (type) {
    682:     case NEP_ERROR_ABSOLUTE:
    683:       break;
    684:     case NEP_ERROR_RELATIVE:
    685:       *error /= PetscAbsScalar(kr)*er;
    686:       break;
    687:     case NEP_ERROR_BACKWARD:
    688:       if (nep->fui!=NEP_USER_INTERFACE_SPLIT) {
    689:         NEPComputeFunction(nep,kr,nep->function,nep->function);
    690:         MatHasOperation(nep->function,MATOP_NORM,&flg);
    691:         if (!flg) SETERRQ(PetscObjectComm((PetscObject)nep),PETSC_ERR_ARG_WRONG,"The computation of backward errors requires a matrix norm operation");
    692:         MatNorm(nep->function,NORM_INFINITY,&nrm);
    693:         *error /= nrm*er;
    694:         break;
    695:       }
    696:       /* initialization of matrix norms */
    697:       if (!nep->nrma[0]) {
    698:         for (j=0;j<nep->nt;j++) {
    699:           MatHasOperation(nep->A[j],MATOP_NORM,&flg);
    700:           if (!flg) SETERRQ(PetscObjectComm((PetscObject)nep),PETSC_ERR_ARG_WRONG,"The computation of backward errors requires a matrix norm operation");
    701:           MatNorm(nep->A[j],NORM_INFINITY,&nep->nrma[j]);
    702:         }
    703:       }
    704:       for (j=0;j<nep->nt;j++) {
    705:         FNEvaluateFunction(nep->f[j],kr,&s);
    706:         z = z + nep->nrma[j]*PetscAbsScalar(s);
    707:       }
    708:       *error /= z*er;
    709:       break;
    710:     default:
    711:       SETERRQ(PetscObjectComm((PetscObject)nep),PETSC_ERR_ARG_OUTOFRANGE,"Invalid error type");
    712:   }
    713:   return(0);
    714: }

    716: /*@
    717:    NEPComputeFunction - Computes the function matrix T(lambda) that has been
    718:    set with NEPSetFunction().

    720:    Collective on nep

    722:    Input Parameters:
    723: +  nep    - the NEP context
    724: -  lambda - the scalar argument

    726:    Output Parameters:
    727: +  A   - Function matrix
    728: -  B   - optional preconditioning matrix

    730:    Notes:
    731:    NEPComputeFunction() is typically used within nonlinear eigensolvers
    732:    implementations, so most users would not generally call this routine
    733:    themselves.

    735:    Level: developer

    737: .seealso: NEPSetFunction(), NEPGetFunction()
    738: @*/
    739: PetscErrorCode NEPComputeFunction(NEP nep,PetscScalar lambda,Mat A,Mat B)
    740: {
    742:   PetscInt       i;
    743:   PetscScalar    alpha;

    747:   NEPCheckProblem(nep,1);
    748:   switch (nep->fui) {
    749:   case NEP_USER_INTERFACE_CALLBACK:
    750:     if (!nep->computefunction) SETERRQ(PetscObjectComm((PetscObject)nep),PETSC_ERR_USER,"Must call NEPSetFunction() first");
    751:     PetscLogEventBegin(NEP_FunctionEval,nep,A,B,0);
    752:     PetscStackPush("NEP user Function function");
    753:     (*nep->computefunction)(nep,lambda,A,B,nep->functionctx);
    754:     PetscStackPop;
    755:     PetscLogEventEnd(NEP_FunctionEval,nep,A,B,0);
    756:     break;
    757:   case NEP_USER_INTERFACE_SPLIT:
    758:     MatZeroEntries(A);
    759:     for (i=0;i<nep->nt;i++) {
    760:       FNEvaluateFunction(nep->f[i],lambda,&alpha);
    761:       MatAXPY(A,alpha,nep->A[i],nep->mstr);
    762:     }
    763:     if (A != B) SETERRQ(PetscObjectComm((PetscObject)nep),1,"Not implemented");
    764:     break;
    765:   }
    766:   return(0);
    767: }

    769: /*@
    770:    NEPComputeJacobian - Computes the Jacobian matrix T'(lambda) that has been
    771:    set with NEPSetJacobian().

    773:    Collective on nep

    775:    Input Parameters:
    776: +  nep    - the NEP context
    777: -  lambda - the scalar argument

    779:    Output Parameters:
    780: .  A   - Jacobian matrix

    782:    Notes:
    783:    Most users should not need to explicitly call this routine, as it
    784:    is used internally within the nonlinear eigensolvers.

    786:    Level: developer

    788: .seealso: NEPSetJacobian(), NEPGetJacobian()
    789: @*/
    790: PetscErrorCode NEPComputeJacobian(NEP nep,PetscScalar lambda,Mat A)
    791: {
    793:   PetscInt       i;
    794:   PetscScalar    alpha;

    798:   NEPCheckProblem(nep,1);
    799:   switch (nep->fui) {
    800:   case NEP_USER_INTERFACE_CALLBACK:
    801:     if (!nep->computejacobian) SETERRQ(PetscObjectComm((PetscObject)nep),PETSC_ERR_USER,"Must call NEPSetJacobian() first");
    802:     PetscLogEventBegin(NEP_JacobianEval,nep,A,0,0);
    803:     PetscStackPush("NEP user Jacobian function");
    804:     (*nep->computejacobian)(nep,lambda,A,nep->jacobianctx);
    805:     PetscStackPop;
    806:     PetscLogEventEnd(NEP_JacobianEval,nep,A,0,0);
    807:     break;
    808:   case NEP_USER_INTERFACE_SPLIT:
    809:     MatZeroEntries(A);
    810:     for (i=0;i<nep->nt;i++) {
    811:       FNEvaluateDerivative(nep->f[i],lambda,&alpha);
    812:       MatAXPY(A,alpha,nep->A[i],nep->mstr);
    813:     }
    814:     break;
    815:   }
    816:   return(0);
    817: }