Skip to content

time_evolve

Computes the real-time evolution,

\[\vert \psi(t) \rangle = e^{-iHt} \vert \psi_0\rangle,\]

of a State \(\vert \psi_0 \rangle\) and a Hermitian operator \(H\) using an iterative algorithm.

Sources
time_evolve.hpp
time_evolve.cpp
time_evolve.jl


Definition

The method is provided in two variants:

  1. Returning a new state while the input state remains untouched. This variant is safe to use and simple to code.

    State time_evolve(OpSum const &H, State psi0, double time,
                      double precision = 1e-12,
                      std::string algorithm = "lanczos");
    
    time_evolve(ops::OpSum, psi0::State, time::Float64; 
                precision::Float64 = 1e-12, 
                algorithm::String = "lanczos")::State
    
  2. An inplace variant time_evolve_inplace, where the input state is overwritten and contains the time evolved state upon exit. This version is more memory efficient than time_evolve.

    void time_evolve_inplace(OpSum const &H, State &psi0, double time,
                             double precision = 1e-12,
                             std::string algorithm = "lanczos");
    
    time_evolve_inplace(ops::OpSum, psi0::State, time::Float64; 
                        precision::Float64 = 1e-12, 
                        algorithm::String = "lanczos")
    

Parameters

Name Description Default
H OpSum defining the hermitian operator \(H\) for time evolution
psi0 initial State \(\vert \psi_0 \rangle\) of the time evolution
time time \(t\) until which the state is evolved
precision accuracy of the computed time evolved state \(\vert \psi(t) \rangle\) 1e-12
algorithm iterative algorithm which is used, one of lanczos or expokit lanczos

The algorithm parameter decised which backend is run. If lanczos is chosen, the evolve_lanczos routine is called with the standard arguments. Alternatively, expokit chooses the time_evolve_expokit routine. For a detailed documentation of the algorithms we refer to the evolve_lanczos and time_evolve_expokit pages. Broadly speaking, the expokit can yield higher precision states at arbitrarily long times at the cost of increased memory and computing time. In practice, we recommend analysing the effect of the precision parameters on the time evolution series obtained in both cases.


Usage Example

int N = 8;
int nup = N / 2;
auto block = Spinhalf(N, nup);

// Define the nearest-neighbor Heisenberg model
auto ops = OpSum();
for (int i=0; i<N; ++i) {
  ops += Op("SdotS", {i, (i+1) % N});
}

auto psi0 = product_state(block, {"Up", "Dn", "Up", "Dn", "Up", "Dn", "Up", "Dn"});
double time = 1.0;
auto psi = time_evolve(ops, psi0, time);
time_evolve_inplace(ops, psi0, time);
XDIAG_SHOW(isapprox(psi0, psi));
let
    N = 8
    nup = N รท 2
    block = Spinhalf(N, nup)

    # Define the nearest-neighbor Heisenberg model
    ops = OpSum()
    for i in 1:N
        ops += "J" * Op("SdotS", [i, mod1(i+1, N)])
    end
    ops["J"] = 1.0

    psi0 = product_state(block, ["Up", "Dn", "Up", "Dn", "Up", "Dn", "Up", "Dn"])
    time = 1.0
    psi = time_evolve(ops, psi0, time)
    time_evolve_inplace(ops, psi0, time)
    @show isapprox(psi0, psi)
end