Jacobi-Davidson is an iterative method for approximately solving the generalized eigenvalue problem
for a handful of eigenpairs. The matrices are huge and can be general. For ease of discussion we take .
Its major selling point is that it can compute interior eigenvalues without iterating with exactly; approximate solves are enough. For very large matrices it is typically infeasible to do an exact solve per iteration.
Other advantages include the possibility to target any point in the complex plane; freedom in the selection procedure (ordinary / harmonic / refined Ritz pairs); and the possibility to specify a good initial search subspace when one knows approximately the directions of the eigenvectors.
Its main disadvantage is expensive iterations in comparison to Arnoldi and the like.
Subspace methods & Ritz pairs
Jacobi-Davidson is a subspace method, which means that it selects an approximate eigenvector from a low-dimensional search subspace . Clearly one cannot expect to find the exact eigenvector in a small subspace; therefore one requires the residual to be perpendicular to a test space . For now we will assume that these two coincide: . This is called a Galerkin condition.
If the columns of an orthonormal matrix form a basis for , then the above can be summarized as
for . Finding is cheap, because the matrix is small. An approximate eigenpair is then obtained as and is called a Ritz pair. We pick the approximate eigenpair that is of most interest; for instance with a Ritz value closest to a specified target.
Note that iterative methods build these search and test spaces incrementally: each iteration the spaces are expanded by a new basis vector.
Jacobi-Davidson’s search space
Now what really defines Jacobi-Davidson is the way in which it expands the search subspace: it extends it by a vector that would roughly correct the error in the best approximate eigenvector so far. Suppose we find a Ritz pair in our search subspace, then we can improve on this as follows: find a vector and a scalar so that the actual eigenvector and the actual eigenvalue . Let be the residual, then it is not hard to show (noting ) that we have the identity
The term should be really small as it is the product of two errors, so we disregard that. Premultiplying this with the projection matrix which removes components in the direction of we find an equation only in terms of :
This is the correction equation. Having solved it for , we could in principle decide to just update our approximate eigenvector . However, the point of Jacobi-Davidson is rather to extend the search subspace with and repeat the whole process untill the residual is small enough.
Lastly, note that if our matrix is Hermetian, we should try and preserve that. One way is to apply the projection matrix to the other side as well: let and rewrite the correction equation as
Since anyway, this will not influence the solution.
Solving the correction equation (approximately)
Remember the selling point of Jacobi-Davidson? We aren’t even going to solve the correction equation exactly, but only approximately, using a handful of iterations of an iterative method.
It turns out that Krylov methods are an excellent choice for this. The condition is automatically satisfied, since the Krylov subspace
as a whole is automatically orthogonal to , simply because . This means you should take as the initial guess of the solution.
Solving the correction equation for testing purposes
Julia’s multiple dispatch allows some inversion of control when solving the correction equation. In the Jacobi-Davidson routine itself we don’t bother about how the correction is retrieved, but we simply specify that is should do that. So we pass the correction equation solver as an argument to the Jacobi-Davidson routine, and simply call it when needed.
It is useful to have an exact correction equation solver, so you can isolate the components of the algorithm when writing tests. The way to go is to use a direct solver for the augmented linear system
to find .
What’s next?
So far we’ve seen that, given a search and test subspace, we can cheaply compute a Ritz pair as an approximate eigenpair. Jacobi-Davidson is characterized by roughly computing a correction to this approximation and use it to extend the search space.
What we haven’t seen so far is:
- How to find the next eigenpair once a previous one is converged. (This is really easy: simply remove it from the search space and subsequently update the correction equation by requiring orthogonality to the converged vectors as well.)
- Implementation tricks for solving the small-dimensional eigenvalue problem. (Actually you want to use a Schur decomposition rather than an eigenvalue decomposition.)
- How to restart the method when the search subspace becomes to big. (If you use Schur vectors, then this is identical to IRAM’s method.)
- How to incorporate preconditioners when solving the correction equation (You need to apply deflation to the preconditioner as well, but surprisingly it is not required to perform a lot of matrix-vector multiplications.)
- How to extract different types of Ritz pairs from the search subspace. (It turns out harmonic Ritz pairs are better for interior eigenvalue problems. The problem with ordinary Ritz values is that they are typically on their way converging to an exterior eigenvalue, and therefore we could get useless approximate eigenvectors.)
- Actual Julia code. (At this point my code is somewhat Matlab-ish, just coding the ideas to verify I get everything.)
I hope to write more about these things very soon and actually show code.