(ch:nep)= # NEP: Nonlinear Eigenvalue Problems The Nonlinear Eigenvalue Problem (`NEP`) solver object covers the general case where the eigenproblem is nonlinear with respect to the eigenvalue, but it cannot be expressed in terms of a polynomial. We will write the problem as $T(\lambda)x=0$, where $T$ is a matrix-valued function of the eigenvalue $\lambda$. Note that `NEP` does not cover the even more general case of having a nonlinear dependence on the eigenvector $x$. In terms of the user interface, `NEP` is quite similar to previously discussed solvers. The main difference is how to represent the function $T$. We will show different alternatives for this. The `NEP` module of SLEPc has been explained with more detail in {cite:p}`Campos:2021:NEP`, including an algorithmic description of the implemented solvers. {#sec:nep label="sec:nep"} ## General Nonlinear Eigenproblems As in previous chapters, we first set up the notation and briefly review basic properties of the eigenvalue problems to be addressed. In this case, we focus on general nonlinear eigenproblems, that is, those that cannot be expressed in a simpler form such as a polynomial eigenproblem. These problems arise in many applications, such as the discretization of delay differential equations. Some of the methods designed to solve such problems are based on Newton-type iterations, so in some ways `NEP` has similarities to PETSc's nonlinear solvers {external:doc}`SNES`. For background material on the nonlinear eigenproblem, the reader is referred to {cite:p}`Guttel:2017:NEP`, {cite:p}`Mehrmann:2004:NEP`. We consider nonlinear eigenvalue problems of the form ```{math} :label: eq:nep T(\lambda)x=0,\qquad x\neq 0, ``` where $T:\Omega\rightarrow\mathbb{C}^{n\times n}$ is a matrix-valued function that is analytic on an open set of the complex plane $\Omega\subseteq\mathbb{C}$. Assuming that the problem is regular, that is, $\det T(\lambda)$ does not vanish identically, any pair $(\lambda,x)$ satisfying equation {math:numref}`eq:nep` is an eigenpair, where $\lambda\in\Omega$ is the eigenvalue and $x\in\mathbb{C}^n$ is the eigenvector. Linear and polynomial eigenproblems are particular cases of equation {math:numref}`eq:nep`. An example application is the rational eigenvalue problem ```{math} :label: eq:rep -Kx+\lambda Mx+\sum_{j=1}^k\frac{\lambda}{\sigma_j-\lambda}C_jx=0, ``` arising in the study of free vibration of plates with elastically attached masses. Here, all matrices are symmetric, $K$ and $M$ are positive-definite and $C_j$ have small rank. Another example comes from the discretization of parabolic partial differential equations with time delay $\tau$, resulting in ```{math} :label: eq:delay (-\lambda I + A + e^{-\tau\lambda}B)x = 0. ``` ### Split Form Equation {math:numref}`eq:nep` can always be rewritten as ```{math} :label: eq:split \big(A_0f_0(\lambda)+A_1f_1(\lambda)+\cdots+A_{\ell-1}f_{\ell-1}(\lambda)\big)x= \left(\sum_{i=0}^{\ell-1}A_if_i(\lambda)\right)x = 0, ``` where $A_i$ are $n\times n$ matrices and $f_i:\Omega\rightarrow\mathbb{C}$ are analytic functions. We will call equation {math:numref}`eq:split` the split form of the nonlinear eigenvalue problem. Often, the formulation arising from applications already has this form, as illustrated by the examples above. Also, a polynomial eigenvalue problem fits this form, where in this case the $f_i$ functions are the polynomial bases of degree $i$, either monomial or non-monomial. ## Defining the Problem The user interface of the `NEP` package is quite similar to `EPS` and `PEP`. As mentioned above, the main difference is the way in which the eigenproblem is defined. In equation [](#sec:nepjac), we focus on the case where the problem is defined as in PETSc's nonlinear solvers {external:doc}`SNES`, that is, providing user-defined callback functions to compute the nonlinear function matrix, $T(\lambda)$, and its derivative, $T'(\lambda)$. We defer the discussion of using the split form of the nonlinear eigenproblem to section [](#sec:nepsplit). {#sec:nepjac label="sec:nepjac"} ### Using Callback Functions A sample code for solving a nonlinear eigenproblem with `NEP` is shown in figure [](#fig:ex-nep). The usual steps are performed, starting with the creation of the solver context with `NEPCreate`. Then the problem matrices are defined, see discussion below. The call to `NEPSetFromOptions` captures relevant options specified in the command line. The actual solver is invoked with `NEPSolve`. Then, the solution is retrieved with `NEPGetConverged` and `NEPGetEigenpair`. Finally, `NEPDestroy` destroys the object. ```{code-block} c :name: fig:ex-nep :caption: Example code for basic solution with `NEP` using callbacks. NEP nep; /* eigensolver context */ Mat F, J; /* Function and Jacobian matrices */ Vec xr, xi; /* eigenvector, x */ PetscScalar kr, ki; /* eigenvalue, k */ ApplCtx ctx; /* user-defined context */ PetscInt j, nconv; PetscReal error; NEPCreate( PETSC_COMM_WORLD, &nep ); /* create and preallocate F and J matrices */ NEPSetFunction( nep, F, F, FormFunction, &ctx ); NEPSetJacobian( nep, J, FormJacobian, &ctx ); NEPSetFromOptions( nep ); NEPSolve( nep ); NEPGetConverged( nep, &nconv ); for (j=0; j