示例#1
0
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;
    }