Related to trotter gates

Hi,
In C++ documentation time evolving MPS with trotter gate has written as shown below. My question is If I have hamiltonian which is same as shown below with extra site term e.g. B*S^z_j where B is applied magnetic field and S^z_j is z-component of spin operator at site j. How do I write MPS with trotter gate.


for(int b = 1; b <= N-1; ++b)
    {
    auto hterm = op(sites,"Sz",b)*op(sites,"Sz",b+1);
    hterm += 0.5*op(sites,"S+",b)*op(sites,"S-",b+1);
    hterm += 0.5*op(sites,"S-",b)*op(sites,"S+",b+1);

    auto g = BondGate(sites,b,b+1,BondGate::tReal,tstep/2.,hterm);
    gates.push_back(g);
    }

1 Like

To include a single-site Hamiltonian term such as B\ S^z_j you can just make it a two-site term with one of the operators being the identity. So to hterm you would add this:

hterm += B*op(sites,"S^z",b)*op(sites,"Id",b+1);

Be careful however because this will only include the terms up B\ S^z_{N-1}. You will also need to include the last field term outside of your loop:

hterm += B*op(sites,"Id",N-1)*op(sites,"S^z",N);
auto g = BondGate(sites,N-1,N,BondGate::tReal,tstep/2.,hterm);
gates.push_back(g);

Also remember to include this extra last gate as the first gate when making the gates that go in the reverse direction.

P.S. in the future please format math and code in your question. To format math you surrond it with dollar signs like $ math $ and for code with backticks ` code ` for inline code or triple backticks:
```
code
```
for multi-line code.

1 Like
for(int b = 1; b <= N-1; ++b)
    {
    auto hterm = op(sites,"Sz",b)*op(sites,"Sz",b+1);
    hterm += 0.5*op(sites,"S+",b)*op(sites,"S-",b+1);
    hterm += 0.5*op(sites,"S-",b)*op(sites,"S+",b+1);
    hterm += B*op(sites,"S^z",b)*op(sites,"Id",b+1);
    

    auto g = BondGate(sites,b,b+1,BondGate::tReal,tstep/2.,hterm);
    gates.push_back(g);
    }
hterm += B*op(sites,"Id",N-1)*op(sites,"S^z",N);
auto g = BondGate(sites,N-1,N,BondGate::tReal,tstep/2.,hterm);
gates.push_back(g);



for(int b = N-1; b >= 1; --b)
    {
    auto hterm = op(sites,"Sz",b)*op(sites,"Sz",b+1);
    hterm += 0.5*op(sites,"S+",b)*op(sites,"S-",b+1);
    hterm += 0.5*op(sites,"S-",b)*op(sites,"S+",b+1);
    hterm += B*op(sites,"S^z",b)*op(sites,"Id",b+1)

    auto g = BondGate(sites,b,b+1,BondGate::tReal,tstep/2.,hterm);
    gates.push_back(g);
    }
hterm += B*op(sites,"Id",N-1)*op(sites,"S^z",N);
auto g = BondGate(sites,N-1,N,BondGate::tReal,tstep/2.,hterm);
gates.push_back(g);

Is it like this?

Not quite: the second set of Trotter gates needs to be the reverse of the first set of Trotter gates. (One way to do this would be to loop backwards over the entries of gates itself, actually.)

In your code above, the

hterm += B*op(sites,"Id",N-1)*op(sites,"S^z",N);
auto g = BondGate(sites,N-1,N,BondGate::tReal,tstep/2.,hterm);
gates.push_back(g);

part needs to go first when making the second set of gates, before the loop that goes backwards like for(int b = N-1; b >= 1; --b)

The correct pattern of Trotter gates is described in various places, like this example:
https://itensor.github.io/ITensors.jl/stable/tutorials/MPSTimeEvolution.html

Last but not least, I would strongly encourage you to try your code on a small system where you can obtain the exact results, or on some exactly solvable case.

for(int b = 1; b <= N-1; ++b)
    {
    auto hterm = op(sites,"Sz",b)*op(sites,"Sz",b+1);
    hterm += 0.5*op(sites,"S+",b)*op(sites,"S-",b+1);
    hterm += 0.5*op(sites,"S-",b)*op(sites,"S+",b+1);
    hterm += B*op(sites,"Sz",b)*op(sites,"Id",b+1);


    auto g = BondGate(sites,b,b+1,BondGate::tReal,tstep/2,hterm);
    gates.push_back(g);
    }

    hterm += B*op(sites,"Id",N-1)*op(sites,"Sz",N);
    auto g = BondGate(sites,N-1,N,BondGate::tReal,tstep/2,hterm);
    gates.push_back(g);




hterm = B*op(sites,"Id",N-1)*op(sites,"Sz",N);
auto g = BondGate(sites,N-1,N,BondGate::tReal,tstep/2.,hterm);
gates.push_back(g);

for(int b = N-1; b >= 1; --b)
    {
    auto hterm += op(sites,"Sz",b)*op(sites,"Sz",b+1);
    hterm += 0.5*op(sites,"S+",b)*op(sites,"S-",b+1);
    hterm += 0.5*op(sites,"S-",b)*op(sites,"S+",b+1);
    hterm += B*op(sites,"Sz",b)*op(sites,"Id",b+1);

    auto g = BondGate(sites,b,b+1,BondGate::tReal,tstep/2.,hterm);
    gates.push_back(g);
    }

Hi,
I did changes as shown above still I am getting error.

What error are you getting?

1.error: no matching function for call to ‘itensor::BondGate::BondGate(itensor::BasicSiteSet<itensor::SpinHalfSite>&, int, int&, itensor::BondGate::Type, itensor::Real, itensor::AutoMPO&)’
   58 |     auto g = BondGate(sites,N-1,N,BondGate::tReal,tstep/2,hterm);
2. error: no match for ‘operator=’ (operand types are ‘itensor::AutoMPO’ and ‘itensor::ITensor’)
   64 | hterm = B*op(sites,"Id",N-1)*op(sites,"Sz",N);
3. error: no matching function for call to ‘itensor::BondGate::BondGate(itensor::BasicSiteSet<itensor::SpinHalfSite>&, int, int&, itensor::BondGate::Type, itensor::Real, itensor::AutoMPO&)’
   65 | auto g = BondGate(sites,N-1,N,BondGate::tReal,tstep/2.,hterm);

From error message, it looks like you forgot to put auto in front of hterm before your second for loop. Note that hterm is first only defined inside the first for loop so it goes out of scope after that and needs to be redeclared.

error: conflicting declaration ‘auto hterm’
   57 |     auto hterm = B*op(sites,"Id",N-1)*op(sites,"Sz",N);

Error after putting auto hterm.

So, we can’t use this board to go line-by-line through debugging your code. Please take time to read the error messages that you get and make the necessary changes. What do you take from this error message? Please take some time to think about it. Answer below in case you are stuck.

Answer:
it say “conflicting declaration” so there must be another place earlier in your code that a variable called hterm was defined but with a different type that is conflicting with the redeclaration here. Also you are only allowed to declare variables once in the same scope in C++.

Hi,
I have declared new variable name, now code is working well.
Thanks.

1 Like

Glad to hear it’s working!

Hi,
How do I write above trotter gate using periodic boundary conditions?

In general I would not recommend using periodic boundary conditions (PBC) and matrix product states unless absolutely necessary. Could you use open boundaries instead and just study a larger system? Techniques for doing PBC with MPS are very limited, and the ones that exist scale much worse and are much slower than for open boundary conditions.

To answer your question, technically you can implement a PBC Hamiltonian by including a bond (for the case of nearest-neighbor interactions) that connects site 1 to site N. This can work ok with DMRG and time evolution methods like TDVP, but for Trotter gates will probably work very poorly because you would need to “swap” site N all the way to site 2 to apply the gate and swap back, potentially making the entanglement very large along the way.

In summary I would not recommend using Trotter gates and PBC.

1 Like

Hi @miles , In case If I want to use PBC, then how we can write the term connecting first and last site ?

e.g.- If I write the PBC terms as hterm += 1/2 * op("S+",sites[1]) * op("S-",sites[N]) (in julia)

then I get the error saying:

 ERROR: LoadError: You are trying to add an ITensor with indices:
((dim=2|id=810|"S=1/2,Site,n=1")' <Out>
 1: QN("Sz",1) => 1
 2: QN("Sz",-1) => 1, (dim=2|id=810|"S=1/2,Site,n=1") <In>
 1: QN("Sz",1) => 1
 2: QN("Sz",-1) => 1, (dim=2|id=269|"S=1/2,Site,n=6")' <Out>
 1: QN("Sz",1) => 1
 2: QN("Sz",-1) => 1, (dim=2|id=269|"S=1/2,Site,n=6") <In>
 1: QN("Sz",1) => 1
 2: QN("Sz",-1) => 1)

into an ITensor with indices:

((dim=2|id=51|"S=1/2,Site,n=5")' <Out>
1: QN("Sz",1) => 1
2: QN("Sz",-1) => 1, (dim=2|id=51|"S=1/2,Site,n=5") <In>
1: QN("Sz",1) => 1
2: QN("Sz",-1) => 1, (dim=2|id=269|"S=1/2,Site,n=6")' <Out>
1: QN("Sz",1) => 1
2: QN("Sz",-1) => 1, (dim=2|id=269|"S=1/2,Site,n=6") <In>
1: QN("Sz",1) => 1
2: QN("Sz",-1) => 1)

but the indices are not permutations of each other.

Hi, if you have a new question could you please post it as a new topic? Also in the Julia part of the forum instead of the C++ part? Thanks!

About your question here, it looks like the variable called hterm in your code is already an ITensor with the indices of your sites 1 and 6 (and their primes). Then you are adding another ITensor to that with the 5th and 6th site indices, which isn’t allowed. (I.e. you can’t add two ITensors which have different indices.) So there must be an issue with the logic of your code. Hope that helps.