QuantumKitHub / MPSKit.jl

A Julia package dedicated to simulating quantum many-body systems using Matrix Product States (MPS)
MIT License
136 stars 30 forks source link

push! for MPOHamiltonian #49

Open HumpyBlumpy opened 1 year ago

HumpyBlumpy commented 1 year ago

It will be nice to have a push! method for SparseMPO and MPOHamiltonian so as to be able to extend the Hamiltonian when working with nonuniform Hamiltonians and a growing mps window.

maartenvd commented 1 year ago

indeed, but the way sparsempo's are implemented at the moment makes this rather difficult (a single element from a sparsempo - sparsemposlice - should really be a proper object, while at the moment it is a lazy view into its parent). So I'm not entirely sure what the interface of push! should be, what kind of object would you want to push onto the sparsempo?

The good news is that we have been working on a bunch of changes to tensorkit/tensoroperations/strided, amongst which is a new "blocktensormap" type, which will replace the current sparsemposlice. A blocktensormap will act like a regular tensormap (you can permute/contract/multiply with it), and sparsempo will simply be a vector of blocktensormaps, making the implementation of push! trivial.

However this will take a bit more time, so in the meantime I'm more then willing to add a temporary push! interface to mpohamiltonian. Did you have some kind of interface in mind?

HumpyBlumpy commented 1 year ago

So what I have in mind is that we start from a window of some size, and non uniform Hamiltonian of the same size

non_uniform_ham = repeat(ham,10);
# modify non_uniform here

Then, as we time-evolve the state, we also dynamically expand the window

for t in 1:100
     #expand window here

     if window_expanded_right #need to increase non_uniform_ham on the right by one site
          push!(non_uniform_ham,ham)
          #modify non_uniform_ham
     end
    if window_expanded_left #need to increase non_uniform_ham on the left by one site
          pushfirst!(non_uniform_ham,ham)
          #modify non_uniform_ham
     end
     (ψ,ψ_envs) = timestep!(ψ,non_uniform_ham ,dt,TDVP(expalg=Lanczos(tol=TDVP_tol,eager=true)),ψ_envs)

end
HumpyBlumpy commented 1 year ago

My solution currently is to redefine the Hamiltonian every time step, i.e calling non_uniform_ham = repeat(ham,length(ψ));. Is it correct that I should be recalculating the environments like so ψ_envs = environments(ψ,non_uniform_ham ,leftenv(gs_envs,1,gs),rightenv(gs_envs,length(ψ),gs)); every time after I change the Hamiltonian ? My Hamiltonian is time-dependent, in addition to growing the window.

maartenvd commented 1 year ago

I have whipped up a hacky version, but I'm not convinced that this should be included in MPSKit in its curent form:

Base.vcat(s::MPSKit.SparseMPOSlice,o::MPOHamiltonian) = MPOHamiltonian(vcat(s,o.data))
Base.vcat(o::MPOHamiltonian,s::MPSKit.SparseMPOSlice) = MPOHamiltonian(vcat(o.data,s))
function Base.vcat(o::SparseMPO,s::MPSKit.SparseMPOSlice)
    o.odim == s.odim || throw(ArgumentError("unsupported"))

    ndomspaces = similar(o.domspaces,length(o)+1,o.odim);
    ndomspaces[1:end-1,:] = o.domspaces;
    ndomspaces[end,:] = s.domspaces;
    npspaces = [o.pspaces;s.pspace];

    nOs = similar(o.Os,length(o)+1,o.odim,o.odim);
    nOs[1:end-1,:,:] = o.Os;
    nOs[end,:,:] = s.Os;

    SparseMPO(nOs,ndomspaces,npspaces)
end
function Base.vcat(s::MPSKit.SparseMPOSlice,o::SparseMPO)
    o.odim == s.odim || throw(ArgumentError("unsupported"))

    ndomspaces = similar(o.domspaces,length(o)+1,o.odim);
    ndomspaces[2:end,:] = o.domspaces;
    ndomspaces[1,:] = s.domspaces;
    npspaces = [s.pspace;o.pspaces];

    nOs = similar(o.Os,length(o)+1,o.odim,o.odim);
    nOs[2:end,:,:] = o.Os;
    nOs[1,:,:] = s.Os;

    SparseMPO(nOs,ndomspaces,npspaces)
end

Your version of updating the environments is indeed correct! However, we do have some code that supports time dependent hamiltonians of the form sum_i f_i(t) H_i, where the idea is that I can simply calculate the environments of H_i instead of recalculating it every timestep (we're using it at the moment in a project where even the left and right states of the window change under time evolution). Is your hamiltonian of such a form, with not that many different f_i's ?

maartenvd commented 1 year ago

for time dependent hamiltonians, see something like https://github.com/maartenvd/MPSKit.jl/pull/52