Ejemplo n.º 1
0
  static inline const typename Tensor::elt_t
  do_string_order(const iTEBD<Tensor> &psi,
		  const Tensor &Opi, int i, const Tensor &Opmiddle,
		  const Tensor &Opj, int j)
  {
    if (i == j) {
      return expected(psi, mmult(Opi, Opj), i);
    } else if (i > j) {
      return do_string_order(psi, Opj, j, Opmiddle, Opi, i);
    } else if (!psi.is_canonical()) {
      return do_string_order(psi.canonical_form(), Opi, i, Opmiddle, Opj, j);
    } else {
      j = j - i;
      i = i & 1;
      j = j + i;
      Tensor v1 = psi.left_boundary(0);
      Tensor v2 = v1;
      const Tensor none;
      const Tensor *op;
      for (int site = 0; (site <= j) || !(site & 1); ++site) {
        if (site == i)
          op = &Opi;
        else if (site == j)
          op = &Opj;
        else if (site > i && site < j)
          op = &Opmiddle;
        else
          op = &none;
        v1 = propagate_right(v1, psi.combined_matrix(site), *op);
        v2 = propagate_right(v2, psi.combined_matrix(site));
      }
      return trace(v1) / trace(v2);
    }
  }
Ejemplo n.º 2
0
 static inline const typename Tensor::elt_t
 do_expected12(const iTEBD<Tensor> &psi, const Tensor &Op12, int site)
 {
   if (!psi.is_canonical()) {
     return do_expected12(psi.canonical_form(), Op12, site);
   } else {
     tensor::index a, i, b, j;
     const Tensor &AlA = psi.combined_matrix(0);
     const Tensor &BlB = psi.combined_matrix(1);
     AlA.get_dimensions(&a, &i, &b);
     BlB.get_dimensions(&b, &j, &a);
     Tensor v1 = psi.left_boundary(0);
     Tensor v2 = v1;
     if (site & 1) {
       v1 = propagate_right(v1, AlA);
       v2 = v1;
       const Tensor BlBAlA = reshape(fold(BlB, -1, AlA, 0), b, j*i, b);
       v1 = propagate_right(v1, BlBAlA, Op12);
       v2 = propagate_right(v2, BlBAlA);
       v1 = propagate_right(v1, BlB);
       v2 = propagate_right(v2, BlB);
     } else {
       const Tensor AlABlB = reshape(fold(AlA, -1, BlB, 0), a, i*j, a);
       v1 = propagate_right(v1, AlABlB, Op12);
       v2 = propagate_right(v2, AlABlB);
     }
     return trace(v1) / trace(v2);
   }
 }
Ejemplo n.º 3
0
 static inline const Tensor
 do_string_order_many(const iTEBD<Tensor> &psi,
                      const Tensor &Opi, const Tensor &Opmiddle,
                      const Tensor &Opj, int N)
 {
   if (!psi.is_canonical()) {
     return do_string_order_many(psi.canonical_form(), Opi, Opmiddle, Opj, N);
   } else {
     Tensor v1 = psi.left_boundary(0);
     Tensor v2 = v1;
     Tensor output(N);
     Tensor nextv2;
     for (int site = 0; (site < N); ++site) {
       const Tensor &aux = psi.combined_matrix(site);
       Tensor v = propagate_right(v1, aux, site? Opj : mmult(Opi,Opj));
       if (nextv2.size()) {
         v2 = nextv2;
       } else {
         v2 = propagate_right(v2, aux);
       }
       if (!(site & 1)) {
         const Tensor &aux = psi.combined_matrix(site+1);
         nextv2 = propagate_right(v2, aux);
         v = propagate_right(v, aux);
         output.at(site) = trace(v) / trace(nextv2);
       } else {
         nextv2 = Tensor();
         output.at(site) = trace(v) / trace(v2);
       }
       if (site) {
         v1 = propagate_right(v1, aux, Opmiddle);
       } else {
         v1 = propagate_right(v1, aux, Opi);
       }
     }
     return output;
   }
 }
Ejemplo n.º 4
0
  const iTEBD<Tensor>
  evolve_itime(iTEBD<Tensor> psi, const Tensor &H12,
	       double dt, tensor::index nsteps,
	       double tolerance, tensor::index max_dim,
	       tensor::index deltan)
  {
    static const double FR_param[5] =
      {0.67560359597983, 1.35120719195966, -0.17560359597983, -1.70241438391932};

    Tensor eH12[4];
    int method = 2;
    switch (method) {
    case 1:
      /* Second order Trotter expansion */
      eH12[1] = linalg::expm((-dt/2) * H12);
    case 0:
      /* First order Trotter expansion */
      eH12[0] = linalg::expm((-dt) * H12);
      break;
    default:
      /* Fourth order Trotter expansion */
      for (int i = 0; i < 4; i++) {
	eH12[i] = linalg::expm((-dt*FR_param[i]) * H12);
      }
    }
    Tensor Id = Tensor::eye(H12.rows());
    double time = 0;
    double E = energy(psi, H12), S = psi.entropy();
    std::cout.precision(5);
    std::cout << nsteps << ", " << dt << " x " << deltan << " = " << dt * deltan << std::endl;
    RTensor S_growth((deltan < 10)? 10 : deltan);
    RTensor E_growth((deltan < 10)? 10 : deltan);
    S_growth.fill_with_zeros();
    E_growth.fill_with_zeros();
    bool stop = false;
    for (size_t i = 0; (i < nsteps) && (!stop); i++) {
      switch (method) {
      case 0:
	psi = psi.apply_operator(eH12[0], 0, tolerance, max_dim);
	psi = psi.apply_operator(eH12[0], 1, tolerance, max_dim);
	break;
      case 1:
	psi = psi.apply_operator(eH12[1], 0, tolerance, max_dim);
	psi = psi.apply_operator(eH12[0], 1, tolerance, max_dim);
	psi = psi.apply_operator(eH12[1], 0, tolerance, max_dim);
	break;
      default:
	psi = psi.apply_operator(eH12[0], 0, tolerance, max_dim);
	psi = psi.apply_operator(eH12[1], 1, tolerance, max_dim);
	psi = psi.apply_operator(eH12[2], 0, tolerance, max_dim);
	psi = psi.apply_operator(eH12[3], 1, tolerance, max_dim);
	psi = psi.apply_operator(eH12[2], 0, tolerance, max_dim);
	psi = psi.apply_operator(eH12[1], 1, tolerance, max_dim);
	psi = psi.apply_operator(eH12[0], 0, tolerance, max_dim);
      }
      double newE = energy(psi, H12);
      double newS = psi.entropy();
      double dS = S - newS;
      double dE = E - newE;
      double dSdt = avg_change(i, S_growth, dS) / dt;
      double dEdt = avg_change(i, E_growth, dE) / dt;
      S = newS;
      E = newE;
      time += dt;
      if (i > E_growth.size() && ((abs(dSdt) < 1e-6) && (dEdt <= 1e-6))) {
	std::cout << "Entropy and energy converged" << std::endl;
	stop = true;
      }
      if ((deltan && (i % deltan  == 0)) || stop) {
	std::cout << "t=" << time << ";\tE=" << E << ";\tS=" << S
		  << ";\tl=" << std::max(psi.left_dimension(0),
					 psi.right_dimension(0))
		  << std::endl;
	std::cout << "\tdS=" << dS << ";\tdE=" << dE << std::endl;
	std::cout << "\tdSdt=" << dSdt << ";\tdEdt=" << dEdt << std::endl;
      }
    }
    return psi;
  }
Ejemplo n.º 5
0
  const iTEBD<Tensor>
  evolve_itime(iTEBD<Tensor> psi, const Tensor &H12,
	       double dt, tensor::index nsteps,
	       double tolerance, tensor::index max_dim,
	       tensor::index deltan, int method,
               std::vector<double> *energies,
               std::vector<double> *entropies)
  {
    static const double FR_param[5] =
      {0.67560359597983, 1.35120719195966, -0.17560359597983, -1.70241438391932};

    Tensor eH12[4];
    //int method = 2;
    switch (method) {
    case 1:
      /* Second order Trotter expansion */
      eH12[1] = linalg::expm((-dt/2) * H12);
    case 0:
      /* First order Trotter expansion */
      eH12[0] = linalg::expm((-dt) * H12);
      break;
    default:
      /* Fourth order Trotter expansion */
      for (int i = 0; i < 4; i++) {
	eH12[i] = linalg::expm((-dt*FR_param[i]) * H12);
      }
    }
    Tensor Id = Tensor::eye(H12.rows());
    double time = 0;
    psi = psi.canonical_form();
    double E = energy(psi, H12), S = psi.entropy();
    if (energies)
      energies->push_back(E);
    if (entropies)
      entropies->push_back(S);
 
    if (!deltan) {
      deltan = 1;
    }
    std::cout.precision(5);
    std::cout << nsteps << ", " << dt << " x " << deltan
              << " = " << dt * deltan << std::endl;
    std::cout << "t=" << time
              << ";\tE=" << E << "; dE=" << 0.0
              << ";\tS=" << S << "; dS=" << 0.0
              << ";\tl=" << std::max(psi.left_dimension(0),
                                     psi.right_dimension(0))
              << std::endl
              << "l = " << matrix_form(real(psi.left_vector(0)))
              << std::endl;
    for (size_t phases = (nsteps + deltan - 1) / deltan; phases; phases--) {
      for (size_t i = 0; (i < deltan); i++) {
        switch (method) {
        case 0:
          psi = psi.apply_operator(eH12[0], 0, tolerance, max_dim);
          psi = psi.apply_operator(eH12[0], 1, tolerance, max_dim);
          break;
        case 1:
          psi = psi.apply_operator(eH12[1], 0, tolerance, max_dim);
          psi = psi.apply_operator(eH12[0], 1, tolerance, max_dim);
          psi = psi.apply_operator(eH12[1], 0, tolerance, max_dim);
          break;
        default:
          psi = psi.apply_operator(eH12[0], 0, tolerance, max_dim);
          psi = psi.apply_operator(eH12[1], 1, tolerance, max_dim);
          psi = psi.apply_operator(eH12[2], 0, tolerance, max_dim);
          psi = psi.apply_operator(eH12[3], 1, tolerance, max_dim);
          psi = psi.apply_operator(eH12[2], 0, tolerance, max_dim);
          psi = psi.apply_operator(eH12[1], 1, tolerance, max_dim);
          psi = psi.apply_operator(eH12[0], 0, tolerance, max_dim);
        }
        time += dt;
      }
      psi = psi.canonical_form();
      double newE = energy(psi, H12);
      double newS = psi.entropy();
      if (energies)
        energies->push_back(newE);
      if (entropies)
        entropies->push_back(newS);
      std::cout << "t=" << time
                << ";\tE=" << newE << "; dE=" << newE-E
                << ";\tS=" << newS << "; dS=" << newS-S
                << ";\tl=" << std::max(psi.left_dimension(0),
                                       psi.right_dimension(0))
                << std::endl
                << "l = " << matrix_form(real(psi.left_vector(0)))
                << std::endl;
      E = newE;
      S = newS;
    }
    return psi;
  }