Example I: tMPS (MPO based)

In this example, we demonstrate how to use the program at the basic level with line by line explanation.

Models

$$(a + b)^2 = a^2 + 2ab + b^2$$

Parameters Setting

size_t L = paras.getInt("L", 10); 
double hx = paras.getDouble("hx", 0.);
double hz = paras.getDouble("hz", 1.);
double J = paras.getDouble("J", 1.);
double Jzz = paras.getDouble("Jzz", 0.5);
double dt = paras.getDouble("dt",0.01);
double t = paras.getDouble("t", 10.);
size_t measurestep = paras.getInt("measurestep", 10);

auto op = generateNSymSpinOperator<std::complex<double> > ();

nsym_simple_uniform_lattice<std::complex<double> > lattice(L, op.at("id")); 

Hamiltonian Construction

In tMPS, the Hamiltonian and the dissipator are constructed as MPOs.

template<typename _T> 
gc::NSymMPO<_T> 
createSpinChainMPO(const std::map<std::string, gc::TensorNd<_T, 2, SHIFU_MAJOR> >& op, 
                   const gc::nsym_simple_uniform_lattice<_T>& lattice, size_t L, 
                   double hx, 
                   double hz, 
                   double J, 
                   double Jzz) 
{
    assert(L == lattice.size()); 
    gc::NSymMPO<_t> mpo(L); 
    for (size_t i = 0; i < L; ++i) 
    {
        mpo += lattice.generateProdMPO({{i, J * op.at("sp")},{i + 1, op.at("sm")}});
        mpo += lattice.generateProdMPO({{i, J * op.at("sm")},{i + 1, op.at("sp")}});
        mpo += lattice.generateProdMPO({{i, Jzz * op.at("sz")},{i + 1, op.at("sz")}});
    }
}

Function createSpinChainMPO Input:

  1. The operators map op, this map is defined in the main function. Available operators, spins, bosons.
  2. Read in 1D lattice
  3. Size of system L
  4. Other parameters hx, hz, J, Jzz, for Hamiltonian

Initial State Preparation

template <typename _T> 
gc::NSymMPS<_T> 
createNaiveInitialState(const gc::nsym_simple_uniform_lattice<_T>& lattice,
                        size_t L,
                        size_t N)
{
    if (N > L) {
        throw std::runtime_error("Too many particles, local cutoff is too small."); 
    }
    for (size_t i = 0; i < N; ++i) 
    {
        v[i] = 0; 
    }
    return lattice.generateProdMPS(v);
}

Function createNaiveInitialState Input: lattice and size of the initial state. Output: A product nonsymetric MPS. More details about initial state construction refer to here.

Observable Setting

gc::uniformNSymLocalObserver<std:complex<double> > ob(L);
ob.set("su", op.at("su")); 
gc::NSymCorrelation<std::complex<double> > corr(0, L, 2 ,"spsm");
for (size_t i = 0; i < corr.size(); ++i) {
    corr.op1(i) = op.at("sp");
    corr.op2(i) = op.at("sm");
}
ob.measure(mps);
corr.measure(mps);

Time Evolution

Data Saving

Benchmark

The results are benchmarked with the dense matrix time evolution

Complete source code is available at