double twoSiteDMRG(Environment const& mpienv, Hubbard& sites, IQMPS& psi, std::vector<IQMPO>const& Hs, Sweeps const& sweeps, Args const& args) { auto L = sites.N(); auto nSweeps = sweeps.nsweep(); psi.position(1); mpienv.barrier(); std::vector<EnvironmentHandler<IQTensor>*> handlerLeft; std::vector<EnvironmentHandler<IQTensor>*> handlerRight; std::for_each(Hs.begin(), Hs.end(), [&] (IQMPO const& element) { auto left = new EnvironmentHandler<IQTensor>(element, psi, Left, 0, false); handlerLeft.push_back(left); auto right = new EnvironmentHandler<IQTensor>(element, psi, Right, 3, false); handlerRight.push_back(right); }); mpienv.barrier(); auto forN = AutoMPO(sites); for(int j = 1; j <= L; ++j) { forN += 1,"Ntot",j; } MPOt<IQTensor> N(forN); auto forSz = AutoMPO(sites); for(int j = 1; j <= L; ++j) { forSz += 1,"Sz",j; } MPOt<IQTensor> Sz(forSz); double nVal = itensor::overlap(psi, N, psi); double szVal = itensor::overlap(psi, Sz, psi); std::cout << "L " << L << " N " << nVal << " Sz" << szVal << std::endl; double lastExpec = 0; double minExpec; IQMPS minState; std::for_each(Hs.begin(), Hs.end(), [&] (IQMPO const& element) { lastExpec += overlap(psi, element, psi); }); lastExpec = sum(mpienv, lastExpec); if (mpienv.rank() == 0) { printStatus(-1, 0, L, lastExpec, 0, szVal, nVal, maxM(psi)); double minExpec = lastExpec; minState = psi; } vector<Direction> directions {Fromleft, Fromright}; for (int nS = 1; nS <= nSweeps; ++nS) { Args args; args.add("Cutoff",sweeps.cutoff(nS)); args.add("Maxm",sweeps.maxm(nS)); args.add("Minm",sweeps.minm(nS)); args.add("Niter",sweeps.niter(nS)); args.add("Noise",sweeps.noise(nS)); for (Direction &dir : directions) { int start = dir==Fromleft?1:L-1; int end = dir==Fromleft?L-1:1; for (int i = start; dir == Fromleft ? i < end : i > end; dir == Fromleft ? i++ : i--) { IQTensor guess = psi.A(i) * psi.A(i+1); std::vector<IQTensor> leftEn; std::vector<IQTensor> rightEn; std::vector<IQTensor> leftH; std::vector<IQTensor> rightH; std::for_each(handlerLeft.begin(), handlerLeft.end(), [&] (EnvironmentHandler<IQTensor>* handler) { leftEn.push_back(handler->currentElement()); }); std::for_each(handlerRight.begin(), handlerRight.end(), [&] (EnvironmentHandler<IQTensor>* handler) { rightEn.push_back(handler->currentElement()); }); std::for_each(Hs.begin(), Hs.end(), [&] (IQMPO const& H) { leftH.push_back(H.A(i)); rightH.push_back(H.A(i+1)); }); LocalHSum<IQTensor> lop(leftH, rightH, leftEn, rightEn); double expec = MPI_davidson(mpienv, lop, guess, args); mpienv.barrier(); if (i == 1) { MPI_insertBond(mpienv, psi, i, Fromleft, guess, leftEn, leftH, rightH, rightEn, args); } else if (i + 1 == L) { MPI_insertBond(mpienv, psi, i, Fromright, guess, leftEn, leftH, rightH, rightEn, args); } else { MPI_insertBond(mpienv, psi, i, dir, guess, leftEn, leftH, rightH, rightEn, args); } if (mpienv.rank() == 0) { double nVal = itensor::overlap(psi, N, psi); double szVal = itensor::overlap(psi, Sz, psi); printStatus(nS, i, L-i, expec, expec - lastExpec, szVal, nVal, maxM(psi)); if(expec < minExpec) { minExpec = expec; minState = psi; } } broadcast(mpienv, psi); lastExpec = expec; auto doStep = [&] (EnvironmentHandler<IQTensor>* handler) { if (dir == Fromleft) handler->stepToRightWithNewState(psi); else handler->stepToLeftWithNewState(psi); }; std::for_each(handlerLeft.begin(), handlerLeft.end(), doStep); std::for_each(handlerRight.begin(), handlerRight.end(), doStep); } if (dir == Fromright && mpienv.rank() == 0) printOutIO((boost::format("-------------------- Finished Sweep %s of %s ----------------------\n") % nS % nSweeps).str() ); } } std::for_each(handlerLeft.begin(), handlerLeft.end(), [] (EnvironmentHandler<IQTensor>* el) { delete(el); }); std::for_each(handlerRight.begin(), handlerRight.end(), [] (EnvironmentHandler<IQTensor>* el) { delete(el); }); psi = minState; return minExpec; }