# Out of memory when applying gates

**URL:** <https://itensor.discourse.group/t/out-of-memory-when-applying-gates/612>\
**Category:** ITensor Julia Questions\
**Tags:** dmrg, mps\
**Created:** [January 24, 2023, 12:52am UTC](https://itensor.discourse.group/t/out-of-memory-when-applying-gates/612 "2023-01-24T00:52:35Z")\
**Posts on this page:** 5\
**Page:** 1

<div class="post-metadata">

**Author:** ![nticea](https://avatars.discourse-cdn.com/v4/letter/n/eb8c5e/32.png) [@nticea](https://itensor.discourse.group/u/nticea)\
**Post date:** [January 24, 2023, 12:52am UTC](https://itensor.discourse.group/t/out-of-memory-when-applying-gates/612/1 "2023-01-24T00:52:35Z")

</div>

Hi,

Hope this finds you well. I am currently trying to calculate correlations on my ground state MPS. Unfortunately, because of how my lattice is arranged, some of the two-site operators I am trying to apply act on sites that are spaced 6 sites apart. The local site dimension is also very large. In all, this results in huge memory requirements. Here is some code describing my operator and how I am applying it to the MPS:

```julia
"""
This is my operator 
"""
function Δ̂(sites, s1::Int, s2::Int)
    # Δ_ij = 1/√2 * (c↑i c↓j - c↓i c↑j)

    if s1 > s2 # ordering matters! 
        @warn "s1 > s2"
        s1, s2 = s2, s1
    end

    # First part
    Δ1 = op("Cup",sites[s1])
    for s in (s1+1):(s2-1)
        Δ1 *= op("F",sites[s])
    end
    Δ1 *= op("Cdn",sites[s2])

    # Second part 
    Δ2 = op("Cdn",sites[s1])
    for s in (s1+1):(s2-1)
        Δ2 *= op("F",sites[s])
    end
    Δ2 *= op("Cup",sites[s2])

    # Take difference and normalize
    Δ = 1/sqrt(2)*(Δ1 - Δ2)
end

"""
This is my code for applying the operator to an MPS at sites s1 and s2 
"""
function apply_twosite_operator(ϕ::MPS, opname::String, sites, s1::Int, s2::Int)
    ϕ = copy(ϕ)
    if opname == "pSC"
        Π = Π̂(sites, s1, s2)
        return apply(Π, ϕ)     
    elseif opname == "dSC"
        Δ = Δ̂(sites, s1, s2)
        return apply(Δ, ϕ)
    end
    @error "No recognized two-site operator"
end

```

Given that my Hamiltonian involves terms like c^\dagger\_i c\_j, where i and j are 6 sites apart, and the DMRG code runs perfectly fine without throwing an out-of-memory error, I am led to believe that my naive implementation and/or application of the \Delta\_{ij} \propto (c\_{i\uparrow}c\_{j\downarrow} - c\_{\downarrow i}c\_{\uparrow j}) operator is just extremely memory inefficient. Do you have any suggestions? How is this step implemented in the DMRG code?

Thank you very much! Have a great week, and thanks again for all the wonderful work you do with ITensor.

---

<div class="post-metadata">

**Author:** ![miles](https://yyz2.discourse-cdn.com/free1/user_avatar/itensor.discourse.group/miles/32/6_2.png) [@miles](https://itensor.discourse.group/u/miles)\
**Post date:** [January 24, 2023, 4:07am UTC](https://itensor.discourse.group/t/out-of-memory-when-applying-gates/612/2 "2023-01-24T04:07:02Z")

</div>

Thanks for the nice feedback about ITensor!

Yes the way you are making the operator could work ok for short distances but not scale well for longer ones. If I understand your code correctly, then the Δ̂ function is making a single ITensor for the operator, and when s1 and s2 are far apart, this ITensor could have a large number of indices. As you know, the number of elements (memory requirement) of a tensor grows **exponentially** with the number of indices it has.

So I would recommend a different approach here. The simplest one that might work well for you is to make a copy of the wavefunction, then apply the individual “ops” making up your operator to it. Then finally use `inner` to compute the overlap of this “operated on” wavefunction with the original wavefunction. If that’s efficient enough then it could work well and definitely won’t use up a ton of memory.

If that isn’t efficient enough (i.e. becomes slow) then there are more sophisticated ways where you can either mix the application of the operators along with the `inner` computation manually. Or you can make an MPO for your operator and compute things that way (which could actually be a little slower but could be convenient).

---

<div class="post-metadata">

**Author:** ![nticea](https://avatars.discourse-cdn.com/v4/letter/n/eb8c5e/32.png) [@nticea](https://itensor.discourse.group/u/nticea)\
**Post date:** [January 24, 2023, 8:00pm UTC](https://itensor.discourse.group/t/out-of-memory-when-applying-gates/612/3 "2023-01-24T20:00:18Z")

</div>

Thank you very much! I will try this and let you know how it works

---

<div class="post-metadata">

**Author:** ![nticea](https://avatars.discourse-cdn.com/v4/letter/n/eb8c5e/32.png) [@nticea](https://itensor.discourse.group/u/nticea)\
**Post date:** [January 31, 2023, 7:26pm UTC](https://itensor.discourse.group/t/out-of-memory-when-applying-gates/612/4 "2023-01-31T19:26:54Z")

</div>

Just wanted to close this thread with some stats on how Miles’s solution compared to what I had previously:

Old solution: `135.729476 seconds (224.40 M allocations: 39.072 GiB, 6.75% gc time, 36.24% compilation time)`

Miles’s solution (apply the operators sequentially to the MPS): `4.715385 seconds (15.05 M allocations: 2.021 GiB, 9.22% gc time, 21.09% compilation time)`

This is exactly what I was looking for! Thank you very much for the help. Hope you have a great week.

---

<div class="post-metadata">

**Author:** ![miles](https://yyz2.discourse-cdn.com/free1/user_avatar/itensor.discourse.group/miles/32/6_2.png) [@miles](https://itensor.discourse.group/u/miles)\
**Post date:** [February 1, 2023, 3:07am UTC](https://itensor.discourse.group/t/out-of-memory-when-applying-gates/612/5 "2023-02-01T03:07:59Z")

</div>

Glad the new approach solved your issue! Thanks for sharing the timings -
