Date: 2023-01-26T12:19:27+00:00

Actual source code: nepsolve.c
slepc-3.18.2 2023-01-26
Report Typos and Errors

      1: /*
      2:    - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
      3:    SLEPc - Scalable Library for Eigenvalue Problem Computations
      4:    Copyright (c) 2002-, 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:            47(3), 23:1--23:29, 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:   "   volume = \"47\",\n"
     31:   "   number = \"3\",\n"
     32:   "   pages = \"23:1--23:29\",\n"
     33:   "   year = \"2021\",\n"
     34:   "   doi = \"10.1145/3447544\"\n"
     35:   "}\n";

     37: PetscErrorCode NEPComputeVectors(NEP nep)
     38: {
     39:   NEPCheckSolved(nep,1);
     40:   if (nep->state==NEP_STATE_SOLVED) PetscTryTypeMethod(nep,computevectors);
     41:   nep->state = NEP_STATE_EIGENVECTORS;
     42:   return 0;
     43: }

     45: /*@
     46:    NEPSolve - Solves the nonlinear eigensystem.

     48:    Collective on nep

     50:    Input Parameter:
     51: .  nep - eigensolver context obtained from NEPCreate()

     53:    Options Database Keys:
     54: +  -nep_view - print information about the solver used
     55: .  -nep_view_vectors - view the computed eigenvectors
     56: .  -nep_view_values - view the computed eigenvalues
     57: .  -nep_converged_reason - print reason for convergence, and number of iterations
     58: .  -nep_error_absolute - print absolute errors of each eigenpair
     59: .  -nep_error_relative - print relative errors of each eigenpair
     60: -  -nep_error_backward - print backward errors of each eigenpair

     62:    Notes:
     63:    All the command-line options listed above admit an optional argument specifying
     64:    the viewer type and options. For instance, use '-nep_view_vectors binary:myvecs.bin'
     65:    to save the eigenvectors to a binary file, '-nep_view_values draw' to draw the computed
     66:    eigenvalues graphically, or '-nep_error_relative :myerr.m:ascii_matlab' to save
     67:    the errors in a file that can be executed in Matlab.

     69:    Level: beginner

     71: .seealso: NEPCreate(), NEPSetUp(), NEPDestroy(), NEPSetTolerances()
     72: @*/
     73: PetscErrorCode NEPSolve(NEP nep)
     74: {
     75:   PetscInt       i;

     78:   if (nep->state>=NEP_STATE_SOLVED) return 0;
     79:   PetscCitationsRegister(citation,&cited);
     80:   PetscLogEventBegin(NEP_Solve,nep,0,0,0);

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

     95:   /* call solver */
     96:   PetscUseTypeMethod(nep,solve);
     98:   nep->state = NEP_STATE_SOLVED;

    100:   /* Only the first nconv columns contain useful information */
    101:   BVSetActiveColumns(nep->V,0,nep->nconv);
    102:   if (nep->twosided) BVSetActiveColumns(nep->W,0,nep->nconv);

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

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

    114:   /* various viewers */
    115:   NEPViewFromOptions(nep,NULL,"-nep_view");
    116:   NEPConvergedReasonViewFromOptions(nep);
    117:   NEPErrorViewFromOptions(nep);
    118:   NEPValuesViewFromOptions(nep);
    119:   NEPVectorsViewFromOptions(nep);

    121:   /* Remove the initial subspace */
    122:   nep->nini = 0;

    124:   /* Reset resolvent information */
    125:   MatDestroy(&nep->resolvent);
    126:   return 0;
    127: }

    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

    139:    Notes:
    140:    This is available for split operator only.

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

    149:    Level: developer

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

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

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

    175:    Collective on nep

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

    183:    Output Parameters:
    184: +  y   - result vector
    185: .  A   - (optional) Function matrix, for callback interface only
    186: -  B   - (unused) preconditioning matrix

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

    195:    Level: developer

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

    212:   if (nep->fui==NEP_USER_INTERFACE_SPLIT) {
    213:     VecSet(y,0.0);
    214:     for (i=0;i<nep->nt;i++) {
    215:       FNEvaluateFunction(nep->f[i],lambda,&alpha);
    216:       MatMult(nep->A[i],x,v);
    217:       VecAXPY(y,alpha,v);
    218:     }
    219:   } else {
    220:     if (!A) A = nep->function;
    221:     NEPComputeFunction(nep,lambda,A,A);
    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   - (optional) Function matrix, for callback interface only
    241: -  B   - (unused) 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: {
    249:   PetscInt       i;
    250:   PetscScalar    alpha;
    251:   Vec            w;

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

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

    284:    Collective on nep

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

    292:    Output Parameters:
    293: +  y   - result vector
    294: -  A   - (optional) Jacobian matrix, for callback interface only

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

    303:    Level: developer

    305: .seealso: NEPSetSplitOperator(), NEPComputeJacobian()
    306: @*/
    307: PetscErrorCode NEPApplyJacobian(NEP nep,PetscScalar lambda,Vec x,Vec v,Vec y,Mat A)
    308: {
    309:   PetscInt       i;
    310:   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:     if (!A) A = nep->jacobian;
    328:     NEPComputeJacobian(nep,lambda,A);
    329:     MatMult(A,x,y);
    330:   }
    331:   return 0;
    332: }

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

    339:    Not Collective

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

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

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

    354:    Level: intermediate

    356: .seealso: NEPGetConvergedReason(), NEPSetTolerances()
    357: @*/
    358: PetscErrorCode NEPGetIterationNumber(NEP nep,PetscInt *its)
    359: {
    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(), NEPGetEigenpair()
    383: @*/
    384: PetscErrorCode NEPGetConverged(NEP nep,PetscInt *nconv)
    385: {
    388:   NEPCheckSolved(nep,1);
    389:   *nconv = nep->nconv;
    390:   return 0;
    391: }

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

    397:    Not Collective

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

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

    405:    Options Database Key:
    406: .  -nep_converged_reason - print the reason to a viewer

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

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

    420:    Level: intermediate

    422: .seealso: NEPSetTolerances(), NEPSolve(), NEPConvergedReason
    423: @*/
    424: PetscErrorCode NEPGetConvergedReason(NEP nep,NEPConvergedReason *reason)
    425: {
    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;

    476:   NEPCheckSolved(nep,1);

    480:   NEPComputeVectors(nep);
    481:   k = nep->perm[i];

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

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

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

    500:    Logically Collective on nep

    502:    Input Parameters:
    503: +  nep - eigensolver context
    504: -  i   - index of the solution

    506:    Output Parameters:
    507: +  Wr   - real part of left eigenvector
    508: -  Wi   - imaginary part of left eigenvector

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

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

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

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

    526:    Level: intermediate

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

    538:   NEPCheckSolved(nep,1);
    542:   NEPComputeVectors(nep);
    543:   k = nep->perm[i];
    544:   BV_GetEigenvector(nep->W,k,nep->eigi[k],Wr,Wi);
    545:   return 0;
    546: }

    548: /*@
    549:    NEPGetErrorEstimate - Returns the error estimate associated to the i-th
    550:    computed eigenpair.

    552:    Not Collective

    554:    Input Parameters:
    555: +  nep - nonlinear eigensolver context
    556: -  i   - index of eigenpair

    558:    Output Parameter:
    559: .  errest - the error estimate

    561:    Notes:
    562:    This is the error estimate used internally by the eigensolver. The actual
    563:    error bound can be computed with NEPComputeError().

    565:    Level: advanced

    567: .seealso: NEPComputeError()
    568: @*/
    569: PetscErrorCode NEPGetErrorEstimate(NEP nep,PetscInt i,PetscReal *errest)
    570: {
    573:   NEPCheckSolved(nep,1);
    576:   *errest = nep->errest[nep->perm[i]];
    577:   return 0;
    578: }

    580: /*
    581:    NEPComputeResidualNorm_Private - Computes the norm of the residual vector
    582:    associated with an eigenpair.

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

    594:   y = w[0];
    595:   if (nep->fui==NEP_USER_INTERFACE_SPLIT) z = w[1];
    596:   if (adj) NEPApplyAdjoint(nep,lambda,x,z,y,NULL,NULL);
    597:   else NEPApplyFunction(nep,lambda,x,z,y,NULL,NULL);
    598:   VecNorm(y,NORM_2,norm);
    599:   return 0;
    600: }

    602: /*@
    603:    NEPComputeError - Computes the error (based on the residual norm) associated
    604:    with the i-th computed eigenpair.

    606:    Collective on nep

    608:    Input Parameters:
    609: +  nep  - the nonlinear eigensolver context
    610: .  i    - the solution index
    611: -  type - the type of error to compute

    613:    Output Parameter:
    614: .  error - the error

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

    621:    Level: beginner

    623: .seealso: NEPErrorType, NEPSolve(), NEPGetErrorEstimate()
    624: @*/
    625: PetscErrorCode NEPComputeError(NEP nep,PetscInt i,NEPErrorType type,PetscReal *error)
    626: {
    627:   Vec            xr,xi=NULL;
    628:   PetscInt       j,nwork,issplit=0;
    629:   PetscScalar    kr,ki,s;
    630:   PetscReal      er,z=0.0,errorl,nrm;
    631:   PetscBool      flg;

    637:   NEPCheckSolved(nep,1);

    639:   /* allocate work vectors */
    640: #if defined(PETSC_USE_COMPLEX)
    641:   nwork = 2;
    642: #else
    643:   nwork = 3;
    644: #endif
    645:   if (nep->fui==NEP_USER_INTERFACE_SPLIT) {
    646:     issplit = 1;
    647:     nwork++;  /* need an extra work vector for NEPComputeResidualNorm_Private */
    648:   }
    649:   NEPSetWorkVecs(nep,nwork);
    650:   xr = nep->work[issplit+1];
    651: #if !defined(PETSC_USE_COMPLEX)
    652:   xi = nep->work[issplit+2];
    653: #endif

    655:   /* compute residual norms */
    656:   NEPGetEigenpair(nep,i,&kr,&ki,xr,xi);
    657: #if !defined(PETSC_USE_COMPLEX)
    659: #endif
    660:   NEPComputeResidualNorm_Private(nep,PETSC_FALSE,kr,xr,nep->work,error);
    661:   VecNorm(xr,NORM_2,&er);

    663:   /* if two-sided, compute left residual norm and take the maximum */
    664:   if (nep->twosided) {
    665:     NEPGetLeftEigenvector(nep,i,xr,xi);
    666:     NEPComputeResidualNorm_Private(nep,PETSC_TRUE,kr,xr,nep->work,&errorl);
    667:     *error = PetscMax(*error,errorl);
    668:   }

    670:   /* compute error */
    671:   switch (type) {
    672:     case NEP_ERROR_ABSOLUTE:
    673:       break;
    674:     case NEP_ERROR_RELATIVE:
    675:       *error /= PetscAbsScalar(kr)*er;
    676:       break;
    677:     case NEP_ERROR_BACKWARD:
    678:       if (nep->fui!=NEP_USER_INTERFACE_SPLIT) {
    679:         NEPComputeFunction(nep,kr,nep->function,nep->function);
    680:         MatHasOperation(nep->function,MATOP_NORM,&flg);
    682:         MatNorm(nep->function,NORM_INFINITY,&nrm);
    683:         *error /= nrm*er;
    684:         break;
    685:       }
    686:       /* initialization of matrix norms */
    687:       if (!nep->nrma[0]) {
    688:         for (j=0;j<nep->nt;j++) {
    689:           MatHasOperation(nep->A[j],MATOP_NORM,&flg);
    691:           MatNorm(nep->A[j],NORM_INFINITY,&nep->nrma[j]);
    692:         }
    693:       }
    694:       for (j=0;j<nep->nt;j++) {
    695:         FNEvaluateFunction(nep->f[j],kr,&s);
    696:         z = z + nep->nrma[j]*PetscAbsScalar(s);
    697:       }
    698:       *error /= z*er;
    699:       break;
    700:     default:
    701:       SETERRQ(PetscObjectComm((PetscObject)nep),PETSC_ERR_ARG_OUTOFRANGE,"Invalid error type");
    702:   }
    703:   return 0;
    704: }

    706: /*@
    707:    NEPComputeFunction - Computes the function matrix T(lambda) that has been
    708:    set with NEPSetFunction().

    710:    Collective on nep

    712:    Input Parameters:
    713: +  nep    - the NEP context
    714: -  lambda - the scalar argument

    716:    Output Parameters:
    717: +  A   - Function matrix
    718: -  B   - optional preconditioning matrix

    720:    Notes:
    721:    NEPComputeFunction() is typically used within nonlinear eigensolvers
    722:    implementations, so most users would not generally call this routine
    723:    themselves.

    725:    Level: developer

    727: .seealso: NEPSetFunction(), NEPGetFunction()
    728: @*/
    729: PetscErrorCode NEPComputeFunction(NEP nep,PetscScalar lambda,Mat A,Mat B)
    730: {
    731:   PetscInt       i;
    732:   PetscScalar    alpha;

    735:   NEPCheckProblem(nep,1);
    736:   switch (nep->fui) {
    737:   case NEP_USER_INTERFACE_CALLBACK:
    739:     PetscLogEventBegin(NEP_FunctionEval,nep,A,B,0);
    740:     PetscCallBack("NEP user Function function",(*nep->computefunction)(nep,lambda,A,B,nep->functionctx));
    741:     PetscLogEventEnd(NEP_FunctionEval,nep,A,B,0);
    742:     break;
    743:   case NEP_USER_INTERFACE_SPLIT:
    744:     MatZeroEntries(A);
    745:     if (A != B) MatZeroEntries(B);
    746:     for (i=0;i<nep->nt;i++) {
    747:       FNEvaluateFunction(nep->f[i],lambda,&alpha);
    748:       MatAXPY(A,alpha,nep->A[i],nep->mstr);
    749:       if (A != B) MatAXPY(B,alpha,nep->P[i],nep->mstrp);
    750:     }
    751:     break;
    752:   }
    753:   return 0;
    754: }

    756: /*@
    757:    NEPComputeJacobian - Computes the Jacobian matrix T'(lambda) that has been
    758:    set with NEPSetJacobian().

    760:    Collective on nep

    762:    Input Parameters:
    763: +  nep    - the NEP context
    764: -  lambda - the scalar argument

    766:    Output Parameters:
    767: .  A   - Jacobian matrix

    769:    Notes:
    770:    Most users should not need to explicitly call this routine, as it
    771:    is used internally within the nonlinear eigensolvers.

    773:    Level: developer

    775: .seealso: NEPSetJacobian(), NEPGetJacobian()
    776: @*/
    777: PetscErrorCode NEPComputeJacobian(NEP nep,PetscScalar lambda,Mat A)
    778: {
    779:   PetscInt       i;
    780:   PetscScalar    alpha;

    783:   NEPCheckProblem(nep,1);
    784:   switch (nep->fui) {
    785:   case NEP_USER_INTERFACE_CALLBACK:
    787:     PetscLogEventBegin(NEP_JacobianEval,nep,A,0,0);
    788:     PetscCallBack("NEP user Jacobian function",(*nep->computejacobian)(nep,lambda,A,nep->jacobianctx));
    789:     PetscLogEventEnd(NEP_JacobianEval,nep,A,0,0);
    790:     break;
    791:   case NEP_USER_INTERFACE_SPLIT:
    792:     MatZeroEntries(A);
    793:     for (i=0;i<nep->nt;i++) {
    794:       FNEvaluateDerivative(nep->f[i],lambda,&alpha);
    795:       MatAXPY(A,alpha,nep->A[i],nep->mstr);
    796:     }
    797:     break;
    798:   }
    799:   return 0;
    800: }