# DMRG with Multi-Site Updates?

**URL:** https://itensor.discourse.group/t/dmrg-with-multi-site-updates/2079
**Category:** ITensor Julia Questions
**Tags:** dmrg
**Created:** [October 22, 2024, 11:23pm UTC](https://itensor.discourse.group/t/dmrg-with-multi-site-updates/2079 "2024-10-22T23:23:21Z")
**Posts on this page:** 4
**Page:** 1

<div class="post-metadata">

### Author: ![amoghanakru](https://avatars.discourse-cdn.com/v4/letter/a/258eb7/32.png) [@amoghanakru](https://itensor.discourse.group/u/amoghanakru)
#### Post date: [October 22, 2024, 11:23pm UTC](https://itensor.discourse.group/t/dmrg-with-multi-site-updates/2079/1 "2024-10-22T23:23:21Z")

</div>

Hi,

I am curious as to whether there is a simple functionality in the (finite) ITensor DMRG code that lets us change the 2-site update to a more general multi-site update; this is necessary for certain classes of problems to help get DMRG unstuck.

There is of course a way to “cheat” and simply define a d^p dimensional custom Hilbert space containing p on-site qudits, so that using the two-site update on this custom Hilbert space is like doing a 2p-site update from the perspective of a model with only one qudit per unit cell. But this seems rather messy since we would have to redefine our custom Hilbert spaces and reconstruct the on-site operators + Hamiltonian for each value of p. Hence I am wondering if there is any pre-existing functionality that accomplishes this in ITensor.

Thanks,

Amogh

---

<div class="post-metadata">

### Author: ![mtfishman](https://yyz2.discourse-cdn.com/free1/user_avatar/itensor.discourse.group/mtfishman/32/11_2.png) [@mtfishman](https://itensor.discourse.group/u/mtfishman)
#### Post date: [October 23, 2024, 2:08pm UTC](https://itensor.discourse.group/t/dmrg-with-multi-site-updates/2079/2 "2024-10-23T14:08:14Z")

</div>

Unfortunately that’s not available in a simple form for users to use right now.

For broader context, in [ITensorTDVP.jl](https://github.com/ITensor/ITensorTDVP.jl)/[ITensorMPS.jl](https://github.com/ITensor/ITensorMPS.jl) and [ITensorNetworks.jl](https://github.com/ITensor/ITensorNetworks.jl) we are working on next-generation DMRG (and DMRG-like) solvers for MPS and more general tensor networks based around a more general concept of sweeping and updating a tensor network (based on the internal `alternating_update` function).

This will provide a lot more flexibility than the standard `ITensors.dmrg` function which is very hardcoded to a certain sweep pattern, 2-site updates, and performing DMRG by updating with an eigensolver. However, the new codes are still hard coded to either doing 1-site or 2-site updates in certain places, but we plan to generalize beyond that to n-site updates (which will be easier to do in those more general settings).

---

<div class="post-metadata">

### Author: ![corbett5](https://yyz2.discourse-cdn.com/free1/user_avatar/itensor.discourse.group/corbett5/32/886_2.png) [@corbett5](https://itensor.discourse.group/u/corbett5)
#### Post date: [October 23, 2024, 10:56pm UTC](https://itensor.discourse.group/t/dmrg-with-multi-site-updates/2079/3 "2024-10-23T22:56:57Z")

</div>

@amoghanakru I’ve tried out what you suggested with merging neighboring sites. It’s relatively simple to do, below I included the code I used to do this (no guarantee it’s bug free). With some modification you could split the sites apart after running DMRG to get back to the original site structure. But I second that it would be nice to easily switch to standard DMRG on an arbitrary number of sites.

```julia
function merge_pairs_of_sites(psi::MPS)::MPS
  @assert mod(length(psi), 2) == 0

  sites = siteinds(psi)
  mergedTensors = Vector{ITensor}()
  for i in 1:2:length(psi)
    mergedTensor = psi[i] * psi[i + 1]
    c = combiner(sites[i], sites[i + 1], dir=dir(sites[i]))
    push!(mergedTensors, mergedTensor * c)
  end

  return MPS(mergedTensors)
end

function merge_pairs_of_sites(H::MPO)::MPO
  @assert mod(length(H), 2) == 0

  sites = noprime(siteinds(first, H))
  mergedTensors = Vector{ITensor}()
  for i in 1:2:length(H)
    cIn = combiner(dag(sites[i]), dag(sites[i + 1]), dir=dir(dag(sites[i])))
    cOut = combiner(prime(sites[i]), prime(sites[i + 1]), dir=dir(prime(sites[i])))
    
    iIn = combinedind(cIn)
    iOut = combinedind(cOut)

    mergedTensor = (H[i] * H[i + 1]) * cIn * cOut
    replaceind!(mergedTensor, iOut, prime(dag(iIn)))

    push!(mergedTensors, mergedTensor)
  end

  return MPO(mergedTensors)
end

function make_sites_match!(H::MPO, psi::MPS)::Nothing
  sitesOfH = noprime(siteinds(first, H))
  sitesOfPsi = siteinds(psi)
  for i in eachindex(psi)
    replaceind!(psi[i], sitesOfPsi[i], sitesOfH[i])
  end

  return nothing
end

```

Usage is

```julia
psi = merge_pairs_of_sites(psi)
H = merge_pairs_of_sites(H)
make_sites_match!(H, psi)

```

---

<div class="post-metadata">

### Author: ![amoghanakru](https://avatars.discourse-cdn.com/v4/letter/a/258eb7/32.png) [@amoghanakru](https://itensor.discourse.group/u/amoghanakru)
#### Post date: [October 24, 2024, 5:33am UTC](https://itensor.discourse.group/t/dmrg-with-multi-site-updates/2079/4 "2024-10-24T05:33:37Z")

</div>

Thank you, this will be very helpful!
