# time-dependent Hamiltonian

0 votes
asked
edited

AbraDabraa!,
Is it possible to evolve the given state with time-dependent Hamiltonian H(t)?
The hamiltonian is periodic, namely H(t)=H(t+T)
More details:

1) I need to find the ground state psi0 of H(0)
2) find psi
t of the Schroedinger eq. with psi0 and H(t)
3) compute the average <psi
t| O | psi_t> of some operator O
4) integrate the result over t

## 2 Answers

+2 votes
answered by (70.1k points)

Hi, yes, so one way to do this is to
1. use DMRG to find the ground state of H(0)
2. use the Trotter gate method to do time evolution as described here:
http://itensor.org/docs.cgi?vers=cppv2&page=formulas/tevol_trotter
but at each time step, use the Hamiltonian H(t) appropriate for that time step to define the gates

Steps 3. and 4. involve computing expectation values the normal way (http://itensor.org/docs.cgi?vers=cppv2&page=formulas/measure_mps) and then the integration for step 4 is up to you to perform as appropriate.

Hope that helps!

Miles

commented by (640 points)
thx. I posted possible answer below.
0 votes
answered by (640 points)
edited

Thank you very much, Miles. I would like to specify the 2nd point of your answer. I understand what you mean, but I can't imagine how it can be done. Could you please write an example.

For instance, how one can replace 'delt' by the function 'delt(t)'

  float delt(float t)
{
return 0.5* sin(t);
}


snippet for Trotter gates

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

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


(and the same for the reverse oder)
time evolve

   gateTEvol(gates,ttotal,tstep,psi,{"Cutoff=",cutoff,"Verbose=",true});


Is there any detailed documentation of 'gateTEvol' function?

Although, I know one of the solutions, which is to divide the total time by N small steps and perform Trotter evolution N times. But i think it is the worst solution.
Thank you in advance!

commented by (70.1k points)
Hi, so actually the solution you are saying about splitting the time into N small steps and performing Trotter evolution N times is in fact the *only* way you can use Trotter evolution at all, even for a time-independent Hamiltonian. If you use Trotter gates for large time steps, each step will make a large error and your results will not be accurate whatsoever. This is an important aspect of Trotter evolution that is important to understand, so please review the background derivation of how Trotter evolution is defined and justified.

Within this context of many small time steps, the idea is that within the loop you do over time steps, you re-make the Trotter gates each time, once per loop over time steps, and make the parameters defining the Hamiltonian terms depend on the time step number.

Best regards,
Miles
commented by (640 points)
I meant to use gateTEvol N times with ttotal=tstep for each step, i.e.

gateTEvol(gates,ttotal=tstep,tstep,psi,{"Cutoff=",cutoff,"Verbose=",true});

for example.

Real t=0;
for(i=1; i<=10;i++)
{
for(int b = 1; b <= N-1; ++b)
{
auto hterm = delt (t)*sites.op("Sz",b)*sites.op("Sz",b+1);
hterm += delt (t)*sites.op("S+",b)*sites.op("S-",b+1);
hterm +=  delt(t)* sites.op("S-",b)*sites.op("S+",b+1);

auto g = Gate(sites,b,b+1,Gate::tReal,tstep/2.,hterm);
gates.push_back(g);
}
gateTEvol(gates,ttotal=tstep,tstep,psi,{"Cutoff=",cutoff,"Verbose=",true});
t=t+tstep*i
}
Is it possible to use gateTEvol only once?
commented by (70.1k points)
Hi, so you're right we need to document gateTEvol. Thanks for the reminder to do that.

In the meantime, here is how it works: given a list/container of gates, which when applied perform one step of time evolution (assumed to be by an amount tstep), will apply these gates a ttotal/tstep number of times until the total time evolved is ttotal. So if you set ttotal and tstep to be equal, it will just apply the gates once to your MPS.  If you want to evolve by more than one time step, just set ttotal to be the time you want to evolve to (it needs to be an integer multiple of tstep).

Internally, gateTEvol is smart about how it adjusts the gauge of the MPS and other technical things to make sure the gates are applied in the most efficient manner possible, given the ordering of the gates (which it accepts and doesn't try to change).

Since your gates are changing with every time step, the way you are using gateTEvol with ttotal equal to tstep seems right to me, unless for some reason you want to change your Hamiltonian only every other time step or something like that.

Finally, it's not standard C++ notation to put assignments (such as ttotal=tstep) into function calls. Technically it's not possible but I would not recommend it. Better to just pass the values you want in the standard way (no equals signs or assignments; if you need to assign to a variable do that before calling the function).

Best regards,
Miles
commented by (640 points)
Thank you very much  for your comments. I used
gateTEvol(gates,tstep,tstep,psi,{"Cutoff=",cutoff,"Verbose=",true});
for some problems and compared the results with an exact diagonalization. The results are coinside with good accuracy. However, I have to construct the new Hamiltonian many times.
For instance, I need to compute the average <psi(T) | O | psi(T)> for different values of the parmeter G. Here  \psi(T) is the wave function at time T of the time-dependent Hamiltonian H(t;G). The Hamiltonian depends on G in the following fashion H(t;G)=H0(t)/G. If, for example, T=10 and G ranges from 0 to 1 with the step G_step=0.01 and tstep=0.01 I have to construct the Hamiltonian 100 x 1000=100000 times :( It takes too much time to compute the desired average even for the systems with 30 sites.
commented by (70.1k points)
Hi, so doing anything complicated 100000 times can be very challenging for modern computers, even with well optimized code. So if you are sure you need to do this many steps, you'll have to keep identifying which parts of the code are taking the most time and finding ways of speeding those up; there's no other way around it and it's not an issue that using another library would immediately help with.

But perhaps you don't really need to do so many calculations? Do you really have to do the measurement every time step? If the value <psi(T)|O|psi(T)> is changing slower than on the time scale of your tstep size, couldn't you do the measurements every 10 time steps for example?

Another optimization is that if the cost of making the Hamiltonian really means the cost of making the Trotter gates, then if you go into how one makes Trotter gates, mostly this involves diagonalizing each term as a small matrix and exponentiating the eigenvalues. But since your Hamiltonians are related by a factor 1/G, this means you could hypothetically save the eigenvectors and just rescale the eigenvalues by G and reuse them. But maybe that's not immediately helpful because you're not changing G for a fixed t. Rather you're changing t for a fixed G, hm...