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; }
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; }