ITensor / ITensorInfiniteMPS.jl

A package for working with infinite matrix product states (MPS) with ITensor.
MIT License
33 stars 21 forks source link

Time evolution using VUMPS #36

Closed ebertok closed 2 years ago

ebertok commented 2 years ago

Recently I started implementing a time-evolution scheme using vumps by adapting code in vumps_localham.jl

The method I'm implementing is the one suggested in 10.1103/PhysRevB.94.165116 on page 35:

image

As I understand it, it should suffice to swap out the eigenvalue problems by exponentials like so (Line 393 in vumps_localham.jl):

for n in 1:Nsites
    Cvecₙ, Cinfoₙ = ITensors.exponentiate(
      Hᶜ(∑h, Hᴸ, Hᴿ, ψ, n), -1im*dt, ψ.C[n], ishermitian=true, tol=krylov_tol
    )
    Avecₙ, Ainfoₙ = ITensors.exponentiate(
      Hᴬᶜ(∑h, Hᴸ, Hᴿ, ψ, n),-1im*dt, ψ.AL[n] * ψ.C[n], ishermitian=true, tol=krylov_tol
    )

    C̃[n] = Cvecₙ
    Ãᶜ[n] = Avecₙ
  end

and for each time-step do only one vumps iteration.

The results for local observables and the time-integrated current are approximately correct, however the errors

 ϵᴸ![n] = norm(Ãᶜ[n] - Ãᴸ[n] * C̃[n])
 ϵᴿ![n] = norm(Ãᶜ[n] - C̃[n - 1] * Ãᴿ[n])

are no longer close to zero but accumulate depending mostly on the time-step. I have verified however, that the imaginary time-evolution gives the same result as vumps.

I could not make it work using the sequential algorithm, so I had to fix the parallel one according to #35 .

Is there something I'm missing that would have to be adapted for time evolution? My code at the moment is very ad-hoc and highly tuned to my specific problem. My fork is https://github.com/ebertok/ITensorInfiniteMPS.jl/tree/time-evolution-VUMPS

mtfishman commented 2 years ago

Hi @ebertok,

Thanks for your interest in the package. We are very interested in adding support for time evolution with TDVP (as well as iTEBD).

Benedikt Kloss is our local tensor network time evolution expert, and he is currently working on developing iTDVP and iTEBD based on this package, so it seems like there is some parallel work going on.

As you noticed as well, he found that naively replacing the eigensolver with exponentiation, at least in the sequential version of VUMPS, does not produce the proper time evolution. His explanation was that you are in fact evolving the bond matrices C twice in a single sweep, so you have to modify the evolution to account for that. He has worked out the details of a fix for the sequential algorithm on paper but hasn't coded it up (this is not something we've seen brought up in the literature).

However, your comments made me realize that these issues indeed may be circumvented by using the parallel version of VUMPS/TDVP, so it sounds like a good way to go to try to fix up the parallel version of VUMPS and implement TDVP based on that. In principle, we should really just have one implementation of the sequential version and one implementation of the parallel version which are written generically to handle TDVP or VUMPS (where only minimal changes are made to switch between VUMPS or TDVP based on swapping out the function for updating AC and C).

We should coordinate with Benedikt on this, but it sounds like you are working on the parallel version and he is working on the sequential version so your work should complement each other.

Like you found as well, he also found there were some cases where complex numbers were not handled properly in the current VUMPS implementation.

So from your side, we would very much welcome a PR that:

  1. Fixed up some of the issues with complex numbers you've fixed in your fork, ideally making it generic to handle both the real and complex cases seen in VUMPS and TDVP.
  2. Fixed the parallel version of VUMPS.
  3. Make a version of TDVP/VUMPS based on the parallel version of VUMPS, sharing most of the code between TDVP and VUMPS by just switching out the solver.

I'm putting together a PR which starts the work of 3. which I will push so you can use it as a reference for how I'm imagining the code design for that.

Cheers, Matt

ebertok commented 2 years ago

Dear @mtfishman

thank you for the detailed answer, I'd be very interested in working together on this. I have come to the same conclusion regarding the sequential time evolution and would also be interested in the proposed fix for this (I have tried evolving each bond matrix only half a time step).

So far I have pretty good results for the time evolution using my parallel version. The only problem I faced is that the precision error linearly increases. But I have no intuition of why they appear.

I also found a non-monotonic error behaviour with increasing the Bond dimension.

In the literature, I found that one has to be careful with gauge fixing, however, this should already be working as intended when using the Polar factorizations. So I'm not sure whether the precision error is even a good error measure in TDVP or whether it's a matter of adapting it.

For completeness: I am using a model with a two atomic basis in both potential and hopping (apparently I implemented a similar fix as has been done recently) and am also interested in a time-dependent Hamiltonian.

Cheers, Eric

mtfishman commented 2 years ago

Hi Eric,

That's great, glad to hear you are interested in helping out.

The precision error is related to the energy gradient (see Appendix A of https://arxiv.org/abs/1701.07035), so is a measure of how close the state is to a variational minimum. From that perspective, it would make sense that time evolution could increase the precision error and is no longer a good measure of the error. I'm not aware of a single error measure that can be used for time evolution with TDVP comparable to the gradiant/precision error (perhaps there is a way to measure the projection error).

The ways I've heard of for assessing the accuracy of TDVP-based time evolution are:

  1. Check for conservation of conserved quantities like energy density (at least in the case of a time-independent Hamiltonian).
  2. Compare to another method like ED to iTEBD. ED would probably be tricky due to finite size effects, of course, so maybe the best way is to do a very high accuracy iTEBD for a short time.
  3. Compare to exact evolution of an integrable model like the transverse field Ising model or free fermions (of course that only assesses the quality of the implementation, not the errors of your specific problem).

I hope that makes sense and helps. I can also ask around for people with more experience with TDVP about how they assess the errors and accuracy.

Cheers, Matt

mtfishman commented 2 years ago

@b-kloss I'd be interested to hear if you agree that the parallel update version of VUMPS is more straightforward for implementing TDVP, and additionally what are good strategies for assessing the accuracy of TDVP.

b-kloss commented 2 years ago

Hi,

b-kloss commented 2 years ago

Also comparing with iTEBD is a good idea of course (there is an implementation in TenPy i think).

mtfishman commented 2 years ago

Thanks @b-kloss, that is helpful.

Indeed, I forgot to mention that the truncation error from the subspace expansion step is a good measure of the error as well. This is limited to the steps where subspace expansion is actually happening, but you can get an idea for the truncation error from the smallest singular values of the bond matrices, which I think I'm already printing out from VUMPS by default.

Also the suggestion of looking at observables as a function of bond dimension is a good one: this is standard procedure for any tensor network method, and a common procedure is to try to make a fit for an observable as a function of bond dimension to get the infinite bond dimension limit. For infinite methods like VUMPS and iTDVP, this is comparable to doing a finite size extrapolation.

mtfishman commented 2 years ago

Partially closed by #37 (at least the parallel version), the sequential version runs but gives incorrect results. We can work that out in another issue.