Question on `eigsolve` in dmrg.jl

Hello,

I am familiarizing myself with the dmrg algorithm and as part of that effort I am reviewing how it is implemented in ITensor in dmrg.jl.

I understand and am able to follow it up until line 260 which is where the call to the eigen solver starts.The code is shown below.

        @timeit_debug timer "dmrg: eigsolve" begin
          vals, vecs = eigsolve(
            PH,
            phi,
            1,
            eigsolve_which_eigenvalue;
            ishermitian=ishermitian,
            tol=eigsolve_tol,
            krylovdim=eigsolve_krylovdim,
            maxiter=eigsolve_maxiter,
          )

I am confused by this call because I looked at KrlovKit.jl eigsolve and its first argument is of type AbstractMatrix. However, the above call passes a AbstractProjMPO as the first argument (the PH) and then an ITensor as the second argument (the phi).

Therefore, I assume ITensor has implemented its own call for eigsolve that does some work prior to calling the eigsolve from KrylovKit.jl. I am interested in inspecting that specialized version of eigsolve however I am not able to find it in the ITensor repo. I am hoping someone can direct me to it. I’m expecting to see something like this

import KryloveKit: eigsolve
function eigsolve(P::AbstractProjMPO, psi::ITensor, kwargs...) 

# some other prep work here, matrix-ization or vectorization of PH and phi
# then a call to eigsolve passing the arguments it expects per eigsolve.jl in KrylovKit

end

I hope that makes sense.

Hi, good question. So we take advantage of the fact that the first argument to KrylovKit eigsolve doesn’t have to be an AbstractMatrix, but according to the KrylovKit docs “can be an AbstractMatrix (dense or sparse) or a general function or callable object”. So we make the PH object callable (accept inputs like a function) and then return the product of the linear operator represented by PH with phi, which gives another ITensor having the same indices as phi.

The linear operator and code to treat it as a callable object for the case where one is performing DMRG on an MPO is is the file src/mps/projmpo.jl.

Thanks for the quick response!

I think what I missed was that ProjMPO was “callable”. The source code you linked shows how it is defined and its constructor. Its not jumping out at me what makes it “callable” based on the code in projmpo.jl. I can make a new post with some follow up questions since you’ve answered this one.

Good point. The code to make it callable isn’t in that file but in the file for the abstract parent type - see line 103:

<https://github.com/ITensor/ITensors.jl/blob/main/src/mps/abstractprojmpo.jl>