14#include "RandomVector.h"
23#ifdef USE_HDF5_STORAGE
24 #include <HDF5Interface.h>
40template<
typename Symmetry,
typename Scalar=
double>
44 static constexpr size_t Nq = Symmetry::Nq;
46 template<
typename Symmetry_,
typename MpHamiltonian,
typename Scalar_>
friend class VumpsSolver;
47 template<
typename Symmetry_,
typename S1,
typename S2>
friend class MpsCompressor;
55 template<
typename Hamiltonian>
Umps (
const Hamiltonian &H,
qarray<Nq> Qtot_input,
size_t L_input,
size_t Mmax,
size_t Nqmax,
bool INIT_TO_HALF_INTEGER_SPIN);
63 #ifdef USE_HDF5_STORAGE
69 Umps (
string filename) {load(filename);}
76 void graph (
string filename)
const;
88 void resize (
size_t Mmax_input,
size_t Nqmax_input,
bool INIT_TO_HALF_INTEGER_SPIN);
129 inline vector<qarray<Symmetry::Nq> >
locBasis (
size_t loc)
const {
return qloc[loc];}
130 inline vector<vector<qarray<Symmetry::Nq> > >
locBasis()
const {
return qloc;}
152 #ifdef USE_HDF5_STORAGE
161 void save (
string filename,
string info=
"none",
double energy=std::nan(
"1"),
double err_var=std::nan(
"1"),
double err_state=std::nan(
"1"));
168 void load (
string filename,
double &energy=dump_Mps,
double &err_var=dump_Mps,
double &err_state=dump_Mps);
192 double memory (MEMUNIT memunit)
const;
201 const vector<Biped<Symmetry,MatrixType> > &
A_at (
GAUGE::OPTION g,
size_t loc)
const {
return A[g][loc];};
222 void truncate(
bool SET_AC_RANDOM=
true);
254 template<
typename MpoScalar>
265 void adjustQN (
const size_t number_cells);
306 template<
typename MpoScalar>
308 double kmin=0.,
double kmax=2.*M_PI,
int kpoints=51,
314 template<
typename MpoScalar>
330 template<
typename MpoScalar>
332 double kmin,
double kmax,
int kpoints,
338 template<
typename MpoScalar>
365 vector<vector<qarray<Symmetry::Nq> > >
qloc;
368 std::array<vector<vector<Biped<Symmetry,MatrixType> > >,3>
A;
371 vector<Biped<Symmetry,MatrixType> >
C;
378 vector<map<qarray<Nq>,tuple<ArrayXd,int> > >
SVspec;
391template<
typename Symmetry,
typename Scalar>
397 ss << Symmetry::name() <<
", ";
402 for (
size_t q=0; q<Nq; ++q)
404 ss << Symmetry::kind()[q];
405 if (q!=Nq-1) {ss <<
",";}
407 ss <<
")=(" << Sym::format<Symmetry>(Qtot) <<
"), ";
409 ss <<
"Lcell=" <<
N_sites <<
", ";
410 ss <<
"Mmax=" << calc_Mmax() <<
" (";
411 if (Symmetry::NON_ABELIAN)
413 ss <<
"full=" << calc_fullMmax() <<
", ";
415 ss <<
"Dmax=" << calc_Dmax() <<
"), ";
416 ss <<
"Nqmax=" << calc_Nqmax() <<
", ";
417 ss <<
"S=(" << S.transpose() <<
"), ";
418 ss <<
"mem=" << round(
memory(GB),3) <<
"GB";
423template<
typename Symmetry,
typename Scalar>
424template<
typename Hamiltonian>
426Umps (
const Hamiltonian &H,
qarray<Nq> Qtot_input,
size_t L_input,
size_t Mmax,
size_t Nqmax,
bool INIT_TO_HALF_INTEGER_SPIN)
427:
N_sites(L_input), Qtot(Qtot_input)
433template<
typename Symmetry,
typename Scalar>
436:
N_sites(L_input), Qtot(Qtot_input)
439 for (
size_t l=0; l<
N_sites; ++l) {
qloc[l] = qloc_input;}
441 ::transform_base<Symmetry>(
qloc,
Qtot);
444template<
typename Symmetry,
typename Scalar>
447:
N_sites(L_input), Qtot(Qtot_input)
450 for (
size_t l=0; l<
N_sites; ++l) {
qloc[l] = qloc_input[l];}
452 ::transform_base<Symmetry>(
qloc,
Qtot);
455template<
typename Symmetry,
typename Scalar>
457memory (MEMUNIT memunit)
const
460 for (
size_t l=0; l<
N_sites; ++l)
462 res += C[l].memory(memunit);
463 for (
size_t g=0; g<3; ++g)
464 for (
size_t s=0; s<qloc[l].size(); ++s)
466 res +=
A[g][l][s].memory(memunit);
472template<
typename Symmetry,
typename Scalar>
477 for (
size_t l=0; l<this->
N_sites; ++l)
479 if (inbase[l].Nq() > res) {res = inbase[l].Nq();}
480 if (outbase[l].Nq() > res) {res = outbase[l].Nq();}
485template<
typename Symmetry,
typename Scalar>
490 for (
size_t l=0; l<this->
N_sites; ++l)
492 if (inbase[l].Dmax() > res) {res = inbase[l].Dmax();}
493 if (outbase[l].Dmax() > res) {res = outbase[l].Dmax();}
498template<
typename Symmetry,
typename Scalar>
503 for (
size_t l=0; l<this->
N_sites; ++l)
505 if (inbase[l].M() > res) {res = inbase[l].M();}
506 if (outbase[l].M() > res) {res = outbase[l].M();}
511template<
typename Symmetry,
typename Scalar>
516 for (
size_t l=0; l<this->
N_sites; ++l)
518 if (inbase[l].fullM() > res) {res = inbase[l].fullM();}
519 if (outbase[l].fullM() > res) {res = outbase[l].fullM();}
524template<
typename Symmetry,
typename Scalar>
529 inbase[loc].pullData(
A[g][loc],0);
532template<
typename Symmetry,
typename Scalar>
536 outbase[loc].clear();
537 outbase[loc].pullData(
A[g][loc],1);
540template<
typename Symmetry,
typename Scalar>
542Qtop (
size_t loc)
const
544 return qplusinf<Symmetry::Nq>();
547template<
typename Symmetry,
typename Scalar>
549Qbot (
size_t loc)
const
551 return qminusinf<Symmetry::Nq>();
554template<
typename Symmetry,
typename Scalar>
559 for (
size_t g=0; g<3; ++g)
562 for (
size_t l=0; l<
N_sites; ++l)
564 A[g][l].resize(qloc[l].size());
580template<
typename Symmetry,
typename Scalar>
581template<
typename OtherMatrixType>
593 for (
size_t g=0; g<3; g++) {
A[g].resize(this->
N_sites);}
596 truncWeight.resize(this->
N_sites); truncWeight.setZero();
597 S.resize(this->
N_sites-1); S.setConstant(numeric_limits<double>::quiet_NaN());
600 for (
size_t g=0; g<3; g++)
601 for (
size_t l=0; l<V.
N_sites; ++l)
603 A[g][l].resize(qloc[l].size());
605 for (
size_t s=0; s<qloc[l].size(); ++s)
607 A[g][l][s].in = V.
A[g][l][s].in;
608 A[g][l][s].out = V.
A[g][l][s].out;
609 A[g][l][s].block.resize(V.
A[g][l][s].dim);
610 A[g][l][s].dict = V.
A[g][l][s].dict;
611 A[g][l][s].dim = V.
A[g][l][s].dim;
614 C[l].out = V.
C[l].out;
615 C[l].block.resize(V.
C[l].dim);
616 C[l].dict = V.
C[l].dict;
617 C[l].dim = V.
C[l].dim;
621template<
typename Symmetry,
typename Scalar>
623resize (
size_t Mmax_input,
size_t Nqmax_input,
bool INIT_TO_HALF_INTEGER_SPIN)
629 if (Symmetry::IS_TRIVIAL) {Nqmax = 1;}
630 else if (Symmetry::IS_MODULAR) {Nqmax = min(
static_cast<size_t>(Symmetry::MOD_N),Nqmax_input);}
634 auto take_first_elems = [
this] (
const vector<qarray<Nq> > &qs) -> vector<
qarray<Nq> >
636 vector<qarray<Nq> > out = qs;
640 VectorXd dist_q1(Nq);
641 VectorXd dist_q2(Nq);
642 for (size_t q=0; q<Nq; q++)
645 dist_q1(q) = q1[q] / Delta;
646 dist_q2(q) = q2[q] / Delta;
648 return (dist_q1.norm() < dist_q2.norm())?
true:
false;
653 vector<set<qarray<Symmetry::Nq> > > qinset(
N_sites);
654 vector<set<qarray<Symmetry::Nq> > > qoutset(
N_sites);
655 if (INIT_TO_HALF_INTEGER_SPIN)
657 for (
const auto & q:Symmetry::lowest_qs()) { qoutset[
N_sites-1].insert(q); }
661 qoutset[
N_sites-1].insert(Symmetry::qvacuum());
663 ArrayXi inSize(
N_sites); inSize = 0;
664 ArrayXi outSize(
N_sites); outSize = 0;
666 while (not((inSize == Nqmax).all() and (outSize == Nqmax).all()))
668 for (
size_t l=0; l<
N_sites; ++l)
671 for (
const auto &t:qoutset[index])
673 if (qinset[l].size() < Nqmax)
678 inSize[l] = qinset[l].size();
680 vector<qarray<Symmetry::Nq> > qinvec(qinset[l].size());
681 copy(qinset[l].begin(), qinset[l].end(), qinvec.begin());
683 auto tmp = Symmetry::reduceSilent(qinvec, qloc[l],
true);
684 tmp = take_first_elems(tmp);
685 for (
const auto &t:tmp)
687 if (qoutset[l].size() < Nqmax)
689 qoutset[l].insert(t);
692 outSize[l] = qoutset[l].size();
697 if (Qtot == Symmetry::qvacuum())
699 for (
size_t l=0; l<
N_sites; ++l)
701 auto qinset_tmp = qinset[l];
702 for (
const auto &q:qinset_tmp)
704 if (
auto it=qinset_tmp.find(Symmetry::flip(q)); it==qinset_tmp.end())
706 qinset[l].insert(Symmetry::flip(q));
710 auto qoutset_tmp = qoutset[l];
711 for (
const auto &q:qoutset_tmp)
713 if (
auto it=qoutset_tmp.find(Symmetry::flip(q)); it==qoutset_tmp.end())
715 qoutset[l].insert(Symmetry::flip(q));
721 for (
size_t l=0; l<
N_sites; ++l)
723 vector<qarray<Symmetry::Nq> > qins(qinset[l].size());
724 copy(qinset[l].begin(), qinset[l].end(), qins.begin());
726 vector<qarray<Symmetry::Nq> > qouts(qoutset[l].size());
727 copy(qoutset[l].begin(), qoutset[l].end(), qouts.begin());
728 assert(
Mmax >= qins.size() and
"Choose a greater Minit to have at least one state per QN block.");
729 size_t Dmax_in =
Mmax / qins.size();
730 size_t Dmax_in_remainder =
Mmax%qins.size();
731 assert(
Mmax >= qouts.size() and
"Choose a greater Minit to have at least one state per QN block.");
732 size_t Dmax_out =
Mmax / qouts.size();
733 size_t Dmax_out_remainder =
Mmax%qouts.size();
735 assert(Dmax_in*qins.size()+Dmax_in_remainder ==
Mmax and
"Strange thing in Umps::resize");
736 assert(Dmax_out*qouts.size()+Dmax_out_remainder ==
Mmax and
"Strange thing in Umps::resize");
738 MatrixXd Mtmpqq(Dmax_in,Dmax_out); Mtmpqq.setZero();
739 MatrixXd Mtmp0q(Dmax_in+Dmax_in_remainder,Dmax_out); Mtmp0q.setZero();
740 MatrixXd Mtmpq0(Dmax_in,Dmax_out+Dmax_out_remainder); Mtmpq0.setZero();
741 MatrixXd Mtmp00(Dmax_in+Dmax_in_remainder,Dmax_out+Dmax_out_remainder); Mtmp00.setZero();
743 for (
size_t g=0; g<3; ++g)
744 for (
size_t s=0; s<qloc[l].size(); ++s)
746 for (
const auto &qin:qins)
748 auto qouts = Symmetry::reduceSilent(qloc[l][s], qin);
749 for (
const auto &qout:qouts)
751 if (
auto it=qoutset[l].find(qout); it!=qoutset[l].end())
754 if (qin != Symmetry::qvacuum() and qout != Symmetry::qvacuum() ) {
A[g][l][s].try_push_back(qinout, Mtmpqq);}
755 else if (qin != Symmetry::qvacuum() and qout == Symmetry::qvacuum() ) {
A[g][l][s].try_push_back(qinout, Mtmpq0);}
756 else if (qin == Symmetry::qvacuum() and qout != Symmetry::qvacuum() ) {
A[g][l][s].try_push_back(qinout, Mtmp0q);}
757 else if (qin == Symmetry::qvacuum() and qout == Symmetry::qvacuum() ) {
A[g][l][s].try_push_back(qinout, Mtmp00);}
775 for (
size_t l=0; l<
N_sites; ++l)
777 size_t Dmax =
Mmax / outbase[l].Nq();
778 size_t Dmax_remainder =
Mmax%outbase[l].Nq();
779 assert(Dmax*outbase[l].Nq()+Dmax_remainder ==
Mmax and
"Strange thing in Umps::resize");
781 MatrixXd Mtmpqq(Dmax,Dmax); Mtmpqq.setZero();
782 MatrixXd Mtmp00(Dmax+Dmax_remainder,Dmax+Dmax_remainder); Mtmp00.setZero();
783 for (
size_t qout=0; qout<outbase[l].Nq(); ++qout)
785 if (outbase[l][qout] != Symmetry::qvacuum()) {C[l].try_push_back(
qarray2<Symmetry::Nq>{outbase[l][qout], outbase[l][qout]}, Mtmpqq);}
786 else if (outbase[l][qout] == Symmetry::qvacuum()) {C[l].try_push_back(
qarray2<Symmetry::Nq>{outbase[l][qout], outbase[l][qout]}, Mtmp00);}
790 for (
size_t l=0; l<
N_sites; ++l)
792 C[l] = C[l].sorted();
850template<
typename Symmetry,
typename Scalar>
855 for (
size_t l=0; l<
N_sites; ++l)
857 C[l] = 1./sqrt((C[l].
contract(C[l].adjoint())).trace()) * C[l];
861template<
typename Symmetry,
typename Scalar>
865 for (
size_t l=0; l<
N_sites; ++l)
866 for (
size_t q=0; q<C[l].dim; ++q)
868 for (
size_t a1=0; a1<C[l].block[q].rows(); ++a1)
870 for (
size_t a2=0; a2<=a1; ++a2)
872 C[l].block[q](a1,a2) = threadSafeRandUniform<Scalar,double>(-1.,1.);
873 C[l].block[q](a2,a1) = C[l].block[q](a1,a2);
879 for (
size_t l=0; l<
N_sites; ++l)
880 for (
size_t s=0; s<qloc[l].size(); ++s)
881 for (
size_t q=0; q<
A[
GAUGE::C][l][s].dim; ++q)
882 for (
size_t a1=0; a1<
A[
GAUGE::C][l][s].block[q].rows(); ++a1)
883 for (
size_t a2=0; a2<
A[
GAUGE::C][l][s].block[q].cols(); ++a2)
886 A[
GAUGE::C][l][s].block[q](a1,a2) = threadSafeRandUniform<Scalar,double>(-1.,1.);
890 for (
size_t l=0; l<
N_sites; ++l)
898template<
typename Symmetry,
typename Scalar>
900graph (
string filename)
const
904 ss <<
"#!/usr/bin/dot dot -Tpdf -o " << filename <<
".pdf\n\n";
905 ss <<
"digraph G\n{\n";
906 ss <<
"rankdir = LR;\n";
907 ss <<
"labelloc=\"t\";\n";
908 ss <<
"label=\"Umps: cell size=" <<
N_sites <<
", Q=(";
909 for (
size_t q=0; q<Nq; ++q)
911 ss << Symmetry::kind()[q];
912 if (q!=Nq-1) {ss <<
",";}
914 ss <<
")" <<
"\";\n";
917 ss <<
"\"l=" << 0 <<
", " << Sym::format<Symmetry>(Symmetry::qvacuum()) <<
"\"";
918 ss <<
"[label=" <<
"\"" << Sym::format<Symmetry>(Symmetry::qvacuum()) <<
"\"" <<
"];\n";
921 for (
size_t l=0; l<
N_sites; ++l)
923 ss <<
"subgraph" <<
" cluster_" << l <<
"\n{\n";
924 for (
size_t s=0; s<qloc[l].size(); ++s)
925 for (
size_t q=0; q<
A[
GAUGE::C][l][s].dim; ++q)
927 string qin = Sym::format<Symmetry>(
A[
GAUGE::C][l][s].in[q]);
928 ss <<
"\"l=" << l <<
", " << qin <<
"\"";
929 ss <<
"[label=" <<
"\"" << qin <<
"\"" <<
"];\n";
931 ss <<
"label=\"l=" << l <<
"\"\n";
936 ss <<
"subgraph" <<
" cluster_" <<
N_sites <<
"\n{\n";
937 for (
size_t s=0; s<qloc[
N_sites-1].size(); ++s)
941 ss <<
"\"l=" <<
N_sites <<
", " << qout <<
"\"";
942 ss <<
"[label=" <<
"\"" << qout <<
"\"" <<
"];\n";
944 ss <<
"label=\"l=" <<
N_sites <<
"=0" <<
"\"\n";
948 for (
size_t l=0; l<
N_sites; ++l)
950 for (
size_t s=0; s<qloc[l].size(); ++s)
951 for (
size_t q=0; q<
A[
GAUGE::C][l][s].dim; ++q)
953 string qin = Sym::format<Symmetry>(
A[
GAUGE::C][l][s].in[q]);
954 string qout = Sym::format<Symmetry>(
A[
GAUGE::C][l][s].out[q]);
955 ss <<
"\"l=" << l <<
", " << qin <<
"\"";
957 ss <<
"\"l=" << l+1 <<
", " << qout <<
"\"";
958 ss <<
" [label=\"" <<
A[
GAUGE::C][l][s].block[q].rows() <<
"x" <<
A[
GAUGE::C][l][s].block[q].cols() <<
"\"";
965 ofstream f(filename+
".dot");
970template<
typename Symmetry,
typename Scalar>
975 std::array<string,4> normal_token = {
"A",
"B",
"M",
"X"};
976 std::array<string,4> special_token = {
"\e[4mA\e[0m",
"\e[4mB\e[0m",
"\e[4mM\e[0m",
"\e[4mX\e[0m"};
983 for (
size_t s=1; s<qloc[l].size(); ++s)
988 vector<bool> A_CHECK(Test.
dim);
989 vector<double> A_infnorm(Test.
dim);
990 for (
size_t q=0; q<Test.
dim; ++q)
992 Test.
block[q] -= MatrixType::Identity(Test.
block[q].rows(), Test.
block[q].cols());
993 A_CHECK[q] = Test.
block[q].norm()<
tol ? true :
false;
994 A_infnorm[q] = Test.
block[q].norm();
1001 for (
size_t s=1; s<qloc[l].size(); ++s)
1006 vector<bool> B_CHECK(Test.
dim);
1007 vector<double> B_infnorm(Test.
dim);
1008 for (
size_t q=0; q<Test.
dim; ++q)
1010 Test.
block[q] -= MatrixType::Identity(Test.
block[q].rows(), Test.
block[q].cols());
1011 B_CHECK[q] = Test.
block[q].template lpNorm<Infinity>()<
tol ? true :
false;
1012 B_infnorm[q] = Test.
block[q].template lpNorm<Infinity>();
1017 for (
size_t s=0; s<qloc[l].size(); ++s)
1020 for (
size_t q=0; q<Test.
dim; ++q)
1023 auto it =
A[
GAUGE::C][l][s].dict.find(quple);
1029 vector<double> T_CHECK(Test.
dim);
1032 for (
size_t q=0; q<Test.
dim; ++q)
1036 normsum += Test.
block[q].norm();
1037 T_CHECK[q] = Test.
block[q].norm()<
tol ? true :
false;
1039 if (all_of(T_CHECK.begin(),T_CHECK.end(),[](
bool x){return x;}))
1041 cout <<
"l=" << l <<
", s=" << s <<
", AL[" << l <<
"]*C[" << l <<
"]=AC[" << l <<
"]="
1042 << termcolor::green <<
"true" << termcolor::reset <<
", normsum=" << normsum << endl;
1046 cout <<
"l=" << l <<
", s=" << s <<
", AL[" << l <<
"]*C[" << l <<
"]=AC[" << l <<
"]="
1047 << termcolor::red <<
"false" << termcolor::reset <<
", normsum=" << normsum << endl;
1052 size_t locC = minus1modL(l);
1053 for (
size_t s=0; s<qloc[l].size(); ++s)
1056 for (
size_t q=0; q<Test.
dim; ++q)
1059 auto it =
A[
GAUGE::C][l][s].dict.find(quple);
1065 vector<double> T_CHECK(Test.
dim);
1068 for (
size_t q=0; q<Test.
dim; ++q)
1072 normsum += Test.
block[q].template lpNorm<Infinity>();
1073 T_CHECK[q] = Test.
block[q].template lpNorm<Infinity>()<
tol ? true :
false;
1075 if (all_of(T_CHECK.begin(),T_CHECK.end(),[](
bool x){return x;}))
1077 cout <<
"l=" << l <<
", s=" << s <<
", C[" << locC <<
"]*AR[" << l <<
"]=AC[" << l <<
"]="
1078 << termcolor::green <<
"true" << termcolor::reset <<
", normsum=" << normsum << endl;
1082 cout <<
"l=" << l <<
", s=" << s <<
", C[" << locC <<
"]*AR[" << l <<
"]=AC[" << l <<
"]="
1083 << termcolor::red <<
"false" << termcolor::reset <<
", normsum=" << normsum << endl;
1087 norm(l) = (C[l].contract(C[l].adjoint())).trace();
1090 if (all_of(A_CHECK.begin(),A_CHECK.end(),[](
bool x){return x;}))
1092 sout << termcolor::red;
1093 sout << normal_token[0];
1098 sout << termcolor::green;
1099 sout << normal_token[2];
1102 if (all_of(B_CHECK.begin(),B_CHECK.end(),[](
bool x){return x;}))
1104 sout << termcolor::blue;
1105 sout << normal_token[1];
1110 sout << termcolor::green;
1111 sout << normal_token[2];
1115 sout << termcolor::reset;
1116 sout <<
", norm=" <<
norm.transpose();
1120template<
typename Symmetry,
typename Scalar>
1130 Eigenstate<Biped<Symmetry,Matrix<complex<Scalar>,Dynamic,Dynamic> > > Leigen, Reigen;
1132 #pragma omp parallel sections
1144 auto LxCket = Leigen.state.contract(Vket.
C[
N_sites-1].template cast<MatrixXcd>());
1145 auto RxCdag = Reigen.state.contract( C[
N_sites-1].adjoint().
template cast<MatrixXcd>());
1146 auto mixed = RxCdag.contract(LxCket).trace();
1148 lout <<
"dot: L gauge: " << Leigen.energy
1149 <<
", R gauge: " << Reigen.energy
1150 <<
", diff=" << abs(Leigen.energy-Reigen.energy)
1151 <<
", mixed gauge (?): " << mixed << endl;
1152 return Leigen.energy;
1155template<
typename Symmetry,
typename Scalar>
1160 SVspec[loc].clear();
1164 lout << termcolor::magenta <<
"loc=" << loc << termcolor::reset << endl;
1166 for (
size_t q=0; q<C[loc].dim; ++q)
1168 #ifdef DONT_USE_BDCSVD
1169 JacobiSVD<MatrixType> Jack;
1171 BDCSVD<MatrixType> Jack;
1174 Jack.compute(C[loc].block[q], ComputeThinU|ComputeThinV);
1177 size_t Nnz = (Jack.singularValues().array() > 0.).count();
1178 double Scontrib = -Symmetry::degeneracy(C[loc].in[q]) *
1179 (Jack.singularValues().head(Nnz).array().square() *
1180 Jack.singularValues().head(Nnz).array().square().log()
1200 SVspec[loc].insert(pair<
qarray<Symmetry::Nq>,tuple<ArrayXd,int> >(C[loc].in[q], make_tuple(Jack.singularValues(), Symmetry::degeneracy(C[loc].in[q]))));
1204 lout << termcolor::magenta
1205 <<
"S(" << C[loc].in[q] <<
","
1206 << C[loc].out[q] <<
")=" << Scontrib
1207 <<
", size=" << C[loc].block[q].rows() <<
"x" << C[loc].block[q].cols()
1208 <<
", deg=" << Symmetry::degeneracy(C[loc].in[q])
1209 <<
", #sv=" << Jack.singularValues().rows()
1210 <<
", svs=" << Jack.singularValues().head(min(20,
int(Jack.singularValues().rows()))).transpose()
1211 << termcolor::reset << endl;
1222template<
typename Symmetry,
typename Scalar>
1226 for (
size_t s=0; s<qloc[loc].size(); ++s)
1227 for (
size_t q=0; q<
A[
GAUGE::C][loc][s].dim; ++q)
1229 std::array<qarray2<Symmetry::Nq>,3> quple;
1230 for (
size_t g=0; g<3; ++g)
1232 quple[g] = {
A[g][loc][s].in[q],
A[g][loc][s].out[q]};
1235 for (
size_t g=1; g<3; ++g)
1237 assert(quple[0] == quple[g]);
1245 for (
size_t qout=0; qout<outbase[loc].Nq(); ++qout)
1248 auto it = C[loc].dict.find(quple);
1249 assert(it != C[loc].dict.end());
1250 size_t qC = it->second;
1253 vector<size_t> svec, qvec, Nrowsvec;
1254 for (
size_t s=0; s<qloc[loc].size(); ++s)
1255 for (
size_t q=0; q<
A[
GAUGE::C][loc][s].dim; ++q)
1257 if (
A[
GAUGE::C][loc][s].out[q] == outbase[loc][qout])
1261 Nrowsvec.push_back(
A[
GAUGE::C][loc][s].block[q].rows());
1266 size_t Ncols =
A[
GAUGE::C][loc][svec[0]].block[qvec[0]].cols();
1267 for (
size_t i=1; i<svec.size(); ++i) {assert(
A[
GAUGE::C][loc][svec[i]].block[qvec[i]].cols() == Ncols);}
1268 size_t Nrows = accumulate(Nrowsvec.begin(),Nrowsvec.end(),0);
1275 for (
size_t i=0; i<svec.size(); ++i)
1277 Aclump.block(stitch,0, Nrowsvec[i],Ncols) =
A[
GAUGE::C][loc][svec[i]].block[qvec[i]];
1278 Acmp.block (stitch,0, Nrowsvec[i],Ncols) =
A[
GAUGE::L][loc][svec[i]].block[qvec[i]];
1279 stitch += Nrowsvec[i];
1282 double diff = (Aclump-Acmp*C[loc].block[qC]).
squaredNorm() * Symmetry::coeff_dot(C[loc].in[qC]);
1283 double summ = (Aclump+Acmp*C[loc].block[qC]).
squaredNorm() * Symmetry::coeff_dot(C[loc].in[qC]);
1285 res += min(
diff,summ);
1295 size_t locC = minus1modL(loc);
1297 for (
size_t qin=0; qin<inbase[loc].Nq(); ++qin)
1300 auto it = C[locC].dict.find(quple);
1301 assert(it != C[locC].dict.end());
1302 size_t qC = it->second;
1305 vector<size_t> svec, qvec, Ncolsvec;
1306 for (
size_t s=0; s<qloc[loc].size(); ++s)
1307 for (
size_t q=0; q<
A[
GAUGE::C][loc][s].dim; ++q)
1309 if (
A[
GAUGE::C][loc][s].in[q] == inbase[loc][qin])
1313 Ncolsvec.push_back(
A[
GAUGE::C][loc][s].block[q].cols());
1318 size_t Nrows =
A[
GAUGE::C][loc][svec[0]].block[qvec[0]].rows();
1319 for (
size_t i=1; i<svec.size(); ++i) {assert(
A[
GAUGE::C][loc][svec[i]].block[qvec[i]].rows() == Nrows);}
1320 size_t Ncols = accumulate(Ncolsvec.begin(), Ncolsvec.end(), 0);
1327 for (
size_t i=0; i<svec.size(); ++i)
1329 Aclump.block(0,stitch, Nrows,Ncolsvec[i]) =
A[
GAUGE::C][loc][svec[i]].block[qvec[i]]*
1330 Symmetry::coeff_leftSweep(
1332 A[
GAUGE::C][loc][svec[i]].out[qvec[i]]);
1334 Acmp.block (0,stitch, Nrows,Ncolsvec[i]) =
A[
GAUGE::R][loc][svec[i]].block[qvec[i]]*
1335 Symmetry::coeff_leftSweep(
1337 A[
GAUGE::R][loc][svec[i]].out[qvec[i]]);
1338 stitch += Ncolsvec[i];
1341 double diff = (Aclump-C[locC].block[qC]*Acmp).
squaredNorm() * Symmetry::coeff_dot(C[locC].in[qC]);
1342 double summ = (Aclump+C[locC].block[qC]*Acmp).
squaredNorm() * Symmetry::coeff_dot(C[locC].in[qC]);
1344 res += min(
diff,summ);
1356template<
typename Symmetry,
typename Scalar>
1361 for (
size_t s=0; s<qloc[loc].size(); ++s)
1362 for (
size_t q=0; q<
A[
GAUGE::C][loc][s].dim; ++q)
1364 std::array<qarray2<Symmetry::Nq>,3> quple;
1365 for (
size_t g=0; g<3; ++g)
1367 quple[g] = {
A[g][loc][s].in[q],
A[g][loc][s].out[q]};
1370 for (
size_t g=1; g<3; ++g)
1372 if (quple[0] != quple[g])
1374 cout <<
"g=" << g <<
", quple[0]=(" << quple[0][0] <<
"," << quple[0][1] <<
")" <<
", quple[g]=(" << quple[g][0] <<
"," << quple[g][1] <<
")" << endl;
1376 assert(quple[0] == quple[g]);
1380 #ifdef DONT_USE_BDCSVD
1381 JacobiSVD<MatrixType> Jack;
1383 BDCSVD<MatrixType> Jack;
1389 vector<MatrixType> UC(C[loc].
dim);
1390 for (
size_t q=0; q<C[loc].dim; ++q)
1392 Jack.compute(C[loc].block[q], ComputeThinU|ComputeThinV);
1393 UC[q] = Jack.matrixU() * Jack.matrixV().adjoint();
1396 for (
size_t qout=0; qout<outbase[loc].Nq(); ++qout)
1401 vector<size_t> svec, qvec, Nrowsvec;
1402 for (
size_t s=0; s<qloc[loc].size(); ++s)
1403 for (
size_t q=0; q<
A[
GAUGE::C][loc][s].dim; ++q)
1405 if (
A[
GAUGE::C][loc][s].out[q] == outbase[loc][qout])
1409 Nrowsvec.push_back(
A[
GAUGE::C][loc][s].block[q].rows());
1414 size_t Ncols =
A[
GAUGE::C][loc][svec[0]].block[qvec[0]].cols();
1415 for (
size_t i=1; i<svec.size(); ++i) {assert(
A[
GAUGE::C][loc][svec[i]].block[qvec[i]].cols() == Ncols);}
1416 size_t Nrows = accumulate(Nrowsvec.begin(),Nrowsvec.end(),0);
1421 for (
size_t i=0; i<svec.size(); ++i)
1423 Aclump.block(stitch,0, Nrowsvec[i],Ncols) =
A[
GAUGE::C][loc][svec[i]].block[qvec[i]];
1424 stitch += Nrowsvec[i];
1427 Jack.compute(Aclump,ComputeThinU|ComputeThinV);
1428 MatrixType UL = Jack.matrixU() * Jack.matrixV().adjoint();
1430 auto it = C[loc].dict.find(quple);
1431 assert(it != C[loc].dict.end());
1432 size_t qC = it->second;
1436 for (
size_t i=0; i<svec.size(); ++i)
1438 A[
GAUGE::L][loc][svec[i]].block[qvec[i]] = UL.block(stitch,0, Nrowsvec[i],Ncols) * UC[qC].adjoint();
1439 stitch += Nrowsvec[i];
1444 size_t locC = minus1modL(loc);
1448 vector<MatrixType> UC(C[locC].
dim);
1451 for (
size_t q=0; q<C[locC].dim; ++q)
1453 Jack.compute(C[locC].block[q], ComputeThinU|ComputeThinV);
1454 UC[q] = Jack.matrixU() * Jack.matrixV().adjoint();
1457 for (
size_t qin=0; qin<inbase[loc].Nq(); ++qin)
1462 vector<size_t> svec, qvec, Ncolsvec;
1463 for (
size_t s=0; s<qloc[loc].size(); ++s)
1464 for (
size_t q=0; q<
A[
GAUGE::C][loc][s].dim; ++q)
1466 if (
A[
GAUGE::C][loc][s].in[q] == inbase[loc][qin])
1470 Ncolsvec.push_back(
A[
GAUGE::C][loc][s].block[q].cols());
1475 size_t Nrows =
A[
GAUGE::C][loc][svec[0]].block[qvec[0]].rows();
1476 for (
size_t i=1; i<svec.size(); ++i) {assert(
A[
GAUGE::C][loc][svec[i]].block[qvec[i]].rows() == Nrows);}
1477 size_t Ncols = accumulate(Ncolsvec.begin(), Ncolsvec.end(), 0);
1481 for (
size_t i=0; i<svec.size(); ++i)
1483 Aclump.block(0,stitch, Nrows,Ncolsvec[i]) =
A[
GAUGE::C][loc][svec[i]].block[qvec[i]]*
1484 Symmetry::coeff_leftSweep(
1487 stitch += Ncolsvec[i];
1490 Jack.compute(Aclump,ComputeThinU|ComputeThinV);
1491 MatrixType UR = Jack.matrixU() * Jack.matrixV().adjoint();
1493 auto it = C[locC].dict.find(quple);
1494 assert(it != C[locC].dict.end());
1495 size_t qC = it->second;
1499 for (
size_t i=0; i<svec.size(); ++i)
1501 A[
GAUGE::R][loc][svec[i]].block[qvec[i]] = UC[qC].adjoint() * UR.block(0,stitch, Nrows,Ncolsvec[i])*
1502 Symmetry::coeff_leftSweep(
1504 A[
GAUGE::C][loc][svec[i]].out[qvec[i]]);
1505 stitch += Ncolsvec[i];
1511template<
typename Symmetry,
typename Scalar>
1516 for (
size_t s=0; s<qloc[loc].size(); ++s)
1517 for (
size_t q=0; q<
A[
GAUGE::C][loc][s].dim; ++q)
1519 std::array<qarray2<Symmetry::Nq>,3> quple;
1520 for (
size_t g=0; g<3; ++g)
1522 quple[g] = {
A[g][loc][s].in[q],
A[g][loc][s].out[q]};
1525 for (
size_t g=1; g<3; ++g)
1527 assert(quple[0] == quple[g]);
1533 ArrayXd truncWeightSub(outbase[loc].Nq()); truncWeightSub.setZero();
1535 vector<Biped<Symmetry,MatrixType> > Atmp(qloc[loc].size());
1536 for (
size_t s=0; s<qloc[loc].size(); ++s)
1538 Atmp[s] =
A[
GAUGE::C][loc][s] * C[loc].adjoint();
1542 for (
size_t qout=0; qout<outbase[loc].Nq(); ++qout)
1550 vector<size_t> svec, qvec, Nrowsvec;
1551 for (
size_t s=0; s<qloc[loc].size(); ++s)
1552 for (
size_t q=0; q<Atmp[s].dim; ++q)
1554 if (Atmp[s].out[q] == outbase[loc][qout])
1558 Nrowsvec.push_back(Atmp[s].block[q].rows());
1563 size_t Ncols = Atmp[svec[0]].block[qvec[0]].cols();
1564 for (
size_t i=1; i<svec.size(); ++i) {assert(Atmp[svec[i]].block[qvec[i]].cols() == Ncols);}
1565 size_t Nrows = accumulate(Nrowsvec.begin(),Nrowsvec.end(),0);
1570 for (
size_t i=0; i<svec.size(); ++i)
1572 Aclump.block(stitch,0, Nrowsvec[i],Ncols) = Atmp[svec[i]].block[qvec[i]];
1573 stitch += Nrowsvec[i];
1578 #ifdef DONT_USE_BDCSVD
1579 JacobiSVD<MatrixType> Jack;
1581 BDCSVD<MatrixType> Jack;
1583 Jack.compute(Aclump,ComputeThinU|ComputeThinV);
1584 VectorXd SV = Jack.singularValues();
1587 size_t Nret = Jack.singularValues().rows();
1596 for (
size_t i=0; i<svec.size(); ++i)
1598 A[
GAUGE::L][loc][svec[i]].block[qvec[i]] = Jack.matrixU().block(stitch,0, Nrowsvec[i],Nret) *
1599 Jack.matrixV().adjoint().topRows(Nret);
1600 stitch += Nrowsvec[i];
1603 truncWeight(loc) = truncWeightSub.sum();
1606 size_t locC = minus1modL(loc);
1610 ArrayXd truncWeightSub(inbase[loc].Nq()); truncWeightSub.setZero();
1611 vector<Biped<Symmetry,MatrixType> > Atmp(qloc[loc].size());
1612 for (
size_t s=0; s<qloc[loc].size(); ++s)
1615 Atmp[s] = C[locC].adjoint() *
A[
GAUGE::C][loc][s];
1620 for (
size_t qin=0; qin<inbase[loc].Nq(); ++qin)
1628 vector<size_t> svec, qvec, Ncolsvec;
1629 for (
size_t s=0; s<qloc[loc].size(); ++s)
1630 for (
size_t q=0; q<Atmp[s].dim; ++q)
1632 if (Atmp[s].in[q] == inbase[loc][qin])
1636 Ncolsvec.push_back(Atmp[s].block[q].cols());
1641 size_t Nrows = Atmp[svec[0]].block[qvec[0]].rows();
1642 for (
size_t i=1; i<svec.size(); ++i) {assert(Atmp[svec[i]].block[qvec[i]].rows() == Nrows);}
1643 size_t Ncols = accumulate(Ncolsvec.begin(), Ncolsvec.end(), 0);
1648 for (
size_t i=0; i<svec.size(); ++i)
1650 Aclump.block(0,stitch, Nrows,Ncolsvec[i]) = Atmp[svec[i]].block[qvec[i]]*
1651 Symmetry::coeff_leftSweep(
1652 Atmp[svec[i]].out[qvec[i]],
1653 Atmp[svec[i]].in[qvec[i]]);
1654 stitch += Ncolsvec[i];
1659 #ifdef DONT_USE_BDCSVD
1660 JacobiSVD<MatrixType> Jack;
1662 BDCSVD<MatrixType> Jack;
1664 Jack.compute(Aclump,ComputeThinU|ComputeThinV);
1665 VectorXd SV = Jack.singularValues();
1668 size_t Nret = Jack.singularValues().rows();
1677 for (
size_t i=0; i<svec.size(); ++i)
1679 A[
GAUGE::R][loc][svec[i]].block[qvec[i]] = Jack.matrixU().leftCols(Nret) *
1680 Jack.matrixV().adjoint().block(0,stitch, Nret,Ncolsvec[i])
1682 Symmetry::coeff_leftSweep(
1683 Atmp[svec[i]].in[qvec[i]],
1684 Atmp[svec[i]].out[qvec[i]]);
1685 stitch += Ncolsvec[i];
1688 truncWeight(loc) = truncWeightSub.sum();
1692template<
typename Symmetry,
typename Scalar>
1693vector<vector<Biped<Symmetry,Matrix<complex<Scalar>,Dynamic,Dynamic>>>>
1695 const Mpo<Symmetry,complex<Scalar>> &R,
1699 bool TRANSPOSE=
false,
1700 bool CONJUGATE=
false)
1702 vector<vector<Biped<Symmetry,Matrix<complex<Scalar>,Dynamic,Dynamic>>>> Ares(
A.size());
1703 for (
int l=0; l<
A.size(); ++l) Ares[l].resize(
A[l].size());
1706 auto qloc_cpy = qloc;
1707 auto qauxAl_cpy = qauxAl;
1708 auto qauxAr_cpy = qauxAr;
1710 if (CONJUGATE and not TRANSPOSE)
1712 for (
int l=0; l<
A.size(); ++l)
1713 for (
int s=0; s<
A[l].size(); ++s)
1715 Aprep[l][s] =
A[l][s].conjugate();
1720 int linv =
A.size()-1;
1721 for (
int l=0; l<
A.size(); ++l)
1723 for (
int s=0; s<
A[l].size(); ++s)
1728 Aprep[l][s] =
A[linv][s].adjoint();
1732 Aprep[l][s] =
A[linv][s].transpose();
1737 qloc_cpy[l] = qloc[linv];
1738 qauxAl_cpy[l] = qauxAr[linv];
1739 qauxAr_cpy[l] = qauxAl[linv];
1745 for (
size_t l=0; l<
A.size(); ++l)
1747 contract_AW(Aprep[l], qloc_cpy[l], R.W_at(0), R.opBasis(0),
1748 qauxAl_cpy[l], R.inBasis(0),
1749 qauxAr_cpy[l], R.outBasis(0),
1780template<
typename Symmetry,
typename Scalar>
1785 N.resize(qloc[loc].size());
1789 for (
size_t qin=0; qin<inbase[loc].Nq(); ++qin)
1792 vector<size_t> svec, qvec, Ncolsvec;
1793 for (
size_t s=0; s<qloc[loc].size(); ++s)
1794 for (
size_t q=0; q<
A[
GAUGE::R][loc][s].dim; ++q)
1796 if (
A[
GAUGE::R][loc][s].in[q] == inbase[loc][qin])
1800 Ncolsvec.push_back(
A[
GAUGE::R][loc][s].block[q].cols());
1804 if (Ncolsvec.size() > 0)
1807 size_t Nrows =
A[
GAUGE::R][loc][svec[0]].block[qvec[0]].rows();
1808 for (
size_t i=1; i<svec.size(); ++i) {assert(
A[
GAUGE::R][loc][svec[i]].block[qvec[i]].rows() == Nrows);}
1809 size_t Ncols = accumulate(Ncolsvec.begin(), Ncolsvec.end(), 0);
1813 for (
size_t i=0; i<svec.size(); ++i)
1815 Aclump.block(0,stitch, Nrows,Ncolsvec[i]) =
A[
GAUGE::R][loc][svec[i]].block[qvec[i]]*
1816 Symmetry::coeff_leftSweep(
1819 stitch += Ncolsvec[i];
1822 HouseholderQR<MatrixType> Quirinus(Aclump.adjoint());
1823 MatrixType Qmatrix = Quirinus.householderQ().adjoint();
1824 size_t Nret = Nrows;
1828 for (
size_t i=0; i<svec.size(); ++i)
1830 if (Qmatrix.rows() > Nret)
1832 size_t Nnull = Qmatrix.rows()-Nret;
1833 MatrixType Mtmp = Qmatrix.block(Nret,stitch, Nnull,Ncolsvec[i])*
1834 Symmetry::coeff_leftSweep(
1836 A[
GAUGE::R][loc][svec[i]].out[qvec[i]]);
1837 N[svec[i]].try_push_back(
A[
GAUGE::R][loc][svec[i]].in[qvec[i]],
A[
GAUGE::R][loc][svec[i]].out[qvec[i]], Mtmp);
1839 stitch += Ncolsvec[i];
1847 for (
size_t qout=0; qout<outbase[loc].Nq(); ++qout)
1848 for (
size_t s=0; s<qloc[loc].size(); ++s)
1850 auto qfulls = Symmetry::reduceSilent(outbase[loc][qout], Symmetry::flip(qloc[loc][s]));
1851 for (
const auto &qfull:qfulls)
1854 auto it =
A[
GAUGE::R][loc][s].dict.find(quple);
1855 if (it ==
A[
GAUGE::R][loc][s].dict.end())
1859 Index down=qcomb.
leftAmount(qfull,{outbase[loc][qout], Symmetry::flip(qloc[loc][s])});
1862 auto it = qcomb.
history.find(qfull);
1863 for (
size_t i=0; i<(it->second).size(); i++)
1865 if ((it->second)[i].source ==
qarray2<Nq>{outbase[loc][qout], Symmetry::flip(qloc[loc][s])})
1867 source_dim = (it->second)[i].
dim;
1870 Mtmp.block(down,0,source_dim,outbase[loc].inner_dim(outbase[loc][qout])).setIdentity();
1871 Mtmp.block(down,0,source_dim,outbase[loc].inner_dim(outbase[loc][qout])) *= Symmetry::coeff_leftSweep( qfull,
1872 outbase[loc][qout]);
1875 N[s].push_back(quple, Mtmp);
1886 for (
size_t qout=0; qout<outbase[loc].Nq(); ++qout)
1889 vector<size_t> svec, qvec, Nrowsvec;
1890 for (
size_t s=0; s<qloc[loc].size(); ++s)
1891 for (
size_t q=0; q<
A[
GAUGE::L][loc][s].dim; ++q)
1893 if (
A[
GAUGE::L][loc][s].out[q] == outbase[loc][qout])
1897 Nrowsvec.push_back(
A[
GAUGE::L][loc][s].block[q].rows());
1901 if (Nrowsvec.size() > 0)
1904 size_t Ncols =
A[
GAUGE::L][loc][svec[0]].block[qvec[0]].cols();
1905 for (
size_t i=1; i<svec.size(); ++i) {assert(
A[
GAUGE::L][loc][svec[i]].block[qvec[i]].cols() == Ncols);}
1906 size_t Nrows = accumulate(Nrowsvec.begin(),Nrowsvec.end(),0);
1911 for (
size_t i=0; i<svec.size(); ++i)
1913 Aclump.block(stitch,0, Nrowsvec[i],Ncols) =
A[
GAUGE::L][loc][svec[i]].block[qvec[i]];
1914 stitch += Nrowsvec[i];
1916 HouseholderQR<MatrixType> Quirinus(Aclump);
1917 MatrixType Qmatrix = Quirinus.householderQ();
1918 size_t Nret = Ncols;
1922 for (
size_t i=0; i<svec.size(); ++i)
1924 if (Qmatrix.cols() > Nret)
1926 size_t Nnull = Qmatrix.cols()-Nret;
1927 MatrixType Mtmp = Qmatrix.block(stitch,Nret, Nrowsvec[i],Nnull);
1928 N[svec[i]].try_push_back(
A[
GAUGE::L][loc][svec[i]].in[qvec[i]],
A[
GAUGE::L][loc][svec[i]].out[qvec[i]], Mtmp);
1930 stitch += Nrowsvec[i];
1938 for (
size_t qin=0; qin<inbase[loc].Nq(); ++qin)
1939 for (
size_t s=0; s<qloc[loc].size(); ++s)
1941 auto qfulls = Symmetry::reduceSilent(inbase[loc][qin], qloc[loc][s]);
1942 for (
const auto &qfull:qfulls)
1945 auto it =
A[
GAUGE::L][loc][s].dict.find(quple);
1946 if (it ==
A[
GAUGE::L][loc][s].dict.end())
1950 Index left=qcomb.
leftAmount(qfull,{inbase[loc][qin], qloc[loc][s]});
1953 auto it = qcomb.
history.find(qfull);
1954 for (
size_t i=0; i<(it->second).size(); i++)
1956 if ((it->second)[i].source ==
qarray2<Nq>{inbase[loc][qin], qloc[loc][s]})
1958 source_dim = (it->second)[i].
dim;
1961 Mtmp.block(0,left,inbase[loc].inner_dim(inbase[loc][qin]),source_dim).setIdentity();
1963 N[s].push_back(quple, Mtmp);
1970template<
typename Symmetry,
typename Scalar>
1971template<
typename OtherScalar>
1978 for (
size_t g=0; g<3; ++g)
1979 for (
size_t l=0; l<this->
N_sites; ++l)
1980 for (
size_t s=0; s<qloc[l].size(); ++s)
1981 for (
size_t q=0; q<
A[g][l][s].dim; ++q)
1983 Vout.
A[g][l][s].block[q] =
A[g][l][s].block[q].template cast<OtherScalar>();
1985 for (
size_t l=0; l<this->
N_sites; ++l)
1986 for (
size_t q=0; q<C[l].dim; ++q)
1988 Vout.
C[l].block[q] = C[l].block[q].template cast<OtherScalar>();
1997template<
typename Symmetry,
typename Scalar>
2004 for (
size_t g=0; g<3; ++g)
2005 for (
size_t l=0; l<this->
N_sites; ++l)
2006 for (
size_t s=0; s<qloc[l].size(); ++s)
2007 for (
size_t q=0; q<
A[g][l][s].dim; ++q)
2009 Vout.
A[g][l][s].block[q] =
A[g][l][s].block[q].real();
2011 for (
size_t l=0; l<this->
N_sites; ++l)
2012 for (
size_t q=0; q<C[l].dim; ++q)
2014 Vout.
C[l].block[q] = C[l].block[q].real();
2023template<
typename Symmetry,
typename Scalar>
2025adjustQN (
const size_t number_cells)
2028 for (
size_t g=0; g<3; ++g)
2029 for (
size_t l=0; l<
N_sites; ++l)
2030 for (
size_t s=0; s<qloc[l].size(); ++s)
2032 A[g][l][s] =
A[g][l][s].adjustQN(number_cells);
2036 for (
size_t l=0; l<
N_sites; ++l)
2037 for (
size_t s=0; s<qloc[l].size(); ++s)
2039 qloc[l][s] = ::adjustQN<Symmetry>(qloc[l][s],number_cells);
2046#ifdef USE_HDF5_STORAGE
2047template<
typename Symmetry,
typename Scalar>
2049save (
string filename,
string info,
double energy,
double err_var,
double err_state)
2052 HDF5Interface target(filename, WRITE);
2053 target.create_group(
"As");
2054 target.create_group(
"Cs");
2055 target.create_group(
"qloc");
2056 target.create_group(
"Qtot");
2058 string add_infoLabel =
"add_info";
2063 target.save_scalar(energy,
"energy");
2065 if (!isnan(err_var))
2067 target.save_scalar(err_var,
"err_var");
2069 if (!isnan(err_state))
2071 target.save_scalar(err_state,
"err_state");
2073 target.save_scalar(this->N_sites,
"L");
2074 for (
size_t q=0; q<Nq; q++)
2076 stringstream ss; ss <<
"q=" << q;
2077 target.save_scalar(this->Qtot[q],ss.str(),
"Qtot");
2079 target.save_scalar(this->calc_Dmax(),
"Dmax");
2080 target.save_scalar(this->calc_Nqmax(),
"Nqmax");
2081 target.save_scalar(this->min_Nsv,
"min_Nsv");
2082 target.save_scalar(this->max_Nsv,
"max_Nsv");
2083 target.save_scalar(this->eps_svd,
"eps_svd");
2084 target.save_scalar(this->eps_truncWeight,
"eps_truncWeight");
2085 target.save_char(
info,add_infoLabel.c_str());
2088 for (
size_t l=0; l<this->
N_sites; ++l)
2090 stringstream ss; ss <<
"l=" << l;
2091 target.save_scalar(qloc[l].size(),ss.str(),
"qloc");
2092 for (
size_t s=0; s<qloc[l].size(); ++s)
2093 for (
size_t q=0; q<Nq; q++)
2095 stringstream tt; tt <<
"l=" << l <<
",s=" << s <<
",q=" << q;
2096 target.save_scalar((qloc[l][s])[q],tt.str(),
"qloc");
2102 for (
size_t g=0; g<3; ++g)
2103 for (
size_t l=0; l<this->
N_sites; ++l)
2104 for (
size_t s=0; s<qloc[l].size(); ++s)
2106 stringstream tt; tt <<
"g=" << g <<
",l=" << l <<
",s=" << s;
2107 target.save_scalar(
A[g][l][s].
dim,tt.str());
2108 for (
size_t q=0; q<
A[g][l][s].dim; ++q)
2110 for (
size_t p=0; p<Nq; p++)
2112 stringstream in; in <<
"in,g=" << g <<
",l=" << l <<
",s=" << s <<
",q=" << q <<
",p=" << p;
2113 stringstream out; out <<
"out,g=" << g <<
",l=" << l <<
",s=" << s <<
",q=" << q <<
",p=" << p;
2114 target.save_scalar((
A[g][l][s].in[q])[p],in.str(),
"As");
2115 target.save_scalar((
A[g][l][s].out[q])[p],out.str(),
"As");
2118 ss << g <<
"_" << l <<
"_" << s <<
"_" <<
"(" <<
A[g][l][s].in[q] <<
"," <<
A[g][l][s].out[q] <<
")";
2120 if constexpr (std::is_same<Scalar,complex<double>>::value)
2122 MatrixXd Re =
A[g][l][s].block[q].real();
2123 MatrixXd Im =
A[g][l][s].block[q].imag();
2124 target.save_matrix(Re, label+
"Re",
"As");
2125 target.save_matrix(Im, label+
"Im",
"As");
2129 target.save_matrix(
A[g][l][s].block[q], label,
"As");
2135 for (
size_t l=0; l<this->
N_sites; ++l)
2137 stringstream tt; tt <<
"l=" << l;
2138 target.save_scalar(C[l].
dim,tt.str());
2139 for (
size_t q=0; q<C[l].dim; ++q)
2141 for (
size_t p=0; p<Nq; p++)
2143 stringstream in; in <<
"l=" << l <<
",q=" << q <<
",p=" << p;
2144 target.save_scalar((C[l].in[q])[p],in.str(),
"Cs");
2147 ss << l <<
"_" <<
"(" << C[l].in[q] <<
")";
2149 if constexpr (std::is_same<Scalar,complex<double>>::value)
2151 MatrixXd Re = C[l].block[q].real();
2152 MatrixXd Im = C[l].block[q].imag();
2153 target.save_matrix(Re, label+
"Re",
"Cs");
2154 target.save_matrix(Im, label+
"Im",
"Cs");
2158 target.save_matrix(C[l].block[q],label,
"Cs");
2165template<
typename Symmetry,
typename Scalar>
2167load (
string filename,
double &energy,
double &err_var,
double &err_state)
2170 HDF5Interface source(filename, READ);
2173 if (source.CHECK(
"energy"))
2175 source.load_scalar(energy,
"energy");
2177 if (source.CHECK(
"err_var"))
2179 source.load_scalar(energy,
"err_var");
2181 if (source.CHECK(
"err_state"))
2183 source.load_scalar(energy,
"err_state");
2185 source.load_scalar(this->N_sites,
"L");
2186 for (
size_t q=0; q<Nq; q++)
2188 stringstream ss; ss <<
"q=" << q;
2189 source.load_scalar(this->Qtot[q],ss.str(),
"Qtot");
2191 source.load_scalar(this->eps_svd,
"eps_svd");
2194 if (source.HAS_GROUP(
"eps_truncWeight")) source.load_scalar(this->eps_truncWeight,
"eps_truncWeight");
2195 source.load_scalar(this->min_Nsv,
"min_Nsv");
2196 source.load_scalar(this->max_Nsv,
"max_Nsv");
2199 qloc.resize(this->N_sites);
2200 for (
size_t l=0; l<this->
N_sites; ++l)
2202 stringstream ss; ss <<
"l=" << l;
2204 source.load_scalar(qloc_size,ss.str(),
"qloc");
2205 qloc[l].resize(qloc_size);
2206 for (
size_t s=0; s<qloc[l].size(); ++s)
2207 for (
size_t q=0; q<Nq; q++)
2209 stringstream tt; tt <<
"l=" << l <<
",s=" << s <<
",q=" << q;
2211 source.load_scalar(Q,tt.str(),
"qloc");
2212 (qloc[l][s])[q] = Q;
2215 this->resize_arrays();
2219 for (
size_t g=0; g<3; ++g)
2220 for (
size_t l=0; l<this->
N_sites; ++l)
2221 for (
size_t s=0; s<qloc[l].size(); ++s)
2224 stringstream tt; tt <<
"g=" << g <<
",l=" << l <<
",s=" << s;
2225 source.load_scalar(Asize,tt.str());
2226 for (
size_t q=0; q<Asize; ++q)
2229 for (
size_t p=0; p<Nq; p++)
2231 stringstream in; in <<
"in,g=" << g <<
",l=" << l <<
",s=" << s <<
",q=" << q <<
",p=" << p;
2232 stringstream out; out <<
"out,g=" << g <<
",l=" << l <<
",s=" << s <<
",q=" << q <<
",p=" << p;
2233 source.load_scalar(qin[p],in.str(),
"As");
2234 source.load_scalar(qout[p],out.str(),
"As");
2237 ss << g <<
"_" << l <<
"_" << s <<
"_" <<
"(" << qin <<
"," << qout <<
")";
2240 if constexpr (std::is_same<Scalar,complex<double>>::value)
2243 source.load_matrix(Re, label+
"Re",
"As");
2244 source.load_matrix(Im, label+
"Im",
"As");
2249 source.load_matrix(mat, label,
"As");
2251 A[g][l][s].push_back(qin,qout,mat);
2257 for (
size_t l=0; l<this->
N_sites; ++l)
2260 stringstream tt; tt <<
"l=" << l;
2261 source.load_scalar(Asize,tt.str());
2262 for (
size_t q=0; q<Asize; ++q)
2265 for (
size_t p=0; p<Nq; p++)
2267 stringstream qq; qq <<
"l=" << l <<
",q=" << q <<
",p=" << p;
2268 source.load_scalar(qVal[p],qq.str(),
"Cs");
2271 ss << l <<
"_" <<
"(" << qVal <<
")";
2274 if constexpr (std::is_same<Scalar,complex<double>>::value)
2277 source.load_matrix(Re, label+
"Re",
"Cs");
2278 source.load_matrix(Im, label+
"Im",
"Cs");
2283 source.load_matrix(mat, label,
"Cs");
2285 C[l].push_back(qVal,qVal,mat);
2294template<
typename Symmetry,
typename Scalar>
2298 if (SORT_ALL_GAUGES)
2300 for (
size_t gP=0; gP<3; ++gP)
2301 for (
size_t s=0; s<locBasis(loc).size(); ++s)
2303 A[gP][loc][s] =
A[gP][loc][s].sorted();
2308 for (
size_t s=0; s<locBasis(loc).size(); ++s)
2310 A[g][loc][s] =
A[g][loc][s].sorted();
2315template<
typename Symmetry,
typename Scalar>
2319 for (
size_t q=0; q<outBasis(loc).Nq(); ++q)
2322 auto qC = C[loc].dict.find(quple);
2323 size_t r = outBasis(loc).inner_dim(outBasis(loc)[q]);
2325 if (qC != C[loc].dict.end())
2327 int dr = r-C[loc].block[qC->second].rows();
2328 int dc = c-C[loc].block[qC->second].cols();
2330 C[loc].block[qC->second].conservativeResize(r,c);
2332 C[loc].block[qC->second].bottomRows(dr).setZero();
2333 C[loc].block[qC->second].rightCols(dc).setZero();
2339 C[loc].push_back(quple, Mtmp);
2344template<
typename Symmetry,
typename Scalar>
2348 assert(g !=
GAUGE::C and
"Oouuhh.. you tried to update AC with itself, but we have no bootstrap implemented ;). Use AL or AR.");
2349 for (
size_t s=0; s<locBasis(loc).size(); ++s)
2350 for (
size_t q=0; q<
A[g][loc][s].size(); ++q)
2353 auto it =
A[
GAUGE::C][loc][s].dict.find(quple);
2354 if (it !=
A[
GAUGE::C][loc][s].dict.end())
2356 int dr =
A[g][loc][s].block[q].rows() -
A[
GAUGE::C][loc][s].block[it->second].rows();
2357 int dc =
A[g][loc][s].block[q].cols() -
A[
GAUGE::C][loc][s].block[it->second].cols();
2358 assert(dr >= 0 and dc >= 0 and
"Something went wrong in expand_basis during the VUMPS Algorithm.");
2361 Mtmp.resize(
A[
GAUGE::C][loc][s].block[it->second].rows(),dc); Mtmp.setZero();
2366 MatrixType Mtmp(
A[g][loc][s].block[q].rows(),
A[g][loc][s].block[q].cols());
2368 A[
GAUGE::C][loc][s].push_back(quple,Mtmp);
2373template<
typename Symmetry,
typename Scalar>
2389 for (
const auto & [qin, num_in, plain_in] : inBasis(
loc1))
2390 for (
size_t s=0; s<locBasis(
loc1).size(); ++s)
2392 bool QIN_IS_IN_P=
false;
2393 for (
size_t qP=0; qP<Pcopy[s].size(); ++qP)
2395 if (Pcopy[s].in[qP] == qin)
2397 if (Pcopy[s].block[qP].rows() != plain_in.size())
2399 addBottom(Eigen::Matrix<Scalar,-1,-1>::Zero(plain_in.size() - Pcopy[s].block[qP].rows(),Pcopy[s].block[qP].cols()), Pcopy[s].block[qP]);
2404 if (QIN_IS_IN_P ==
false)
2406 auto qouts = Symmetry::reduceSilent(qin, locBasis(
loc1)[s]);
2407 for (
const auto &qout : qouts)
2409 if (!base_P.
find(qout)) {
continue;}
2410 Pcopy[s].push_back(qin,qout,Eigen::Matrix<Scalar,-1,-1>::Zero(plain_in.size(),base_P.
inner_dim(qout)));
2417 for (
const auto & [qout, num_out, plain_out] : outBasis(
loc1))
2418 for (
size_t s=0; s<locBasis(
loc1).size(); ++s)
2420 bool QOUT_IS_IN_P=
false;
2421 for (
size_t qP=0; qP<Pcopy[s].size(); ++qP)
2423 if (Pcopy[s].out[qP] == qout)
2425 if (Pcopy[s].block[qP].cols() != plain_out.size())
2427 addRight(Eigen::Matrix<Scalar,-1,-1>::Zero(Pcopy[s].block[qP].rows(), plain_out.size() - Pcopy[s].block[qP].cols()), Pcopy[s].block[qP]);
2432 if (QOUT_IS_IN_P ==
false)
2434 auto qins = Symmetry::reduceSilent(qout, Symmetry::flip(locBasis(
loc1)[s]));
2435 for (
const auto &qin : qins)
2437 if (!base_P.
find(qin)) {
continue;}
2438 Pcopy[s].push_back(qin,qout,Eigen::Matrix<Scalar,-1,-1>::Zero(base_P.
inner_dim(qin),plain_out.size()));
2444 for (
size_t s=0; s<locBasis(
loc1).size(); ++s)
2445 for (
size_t qP=0; qP<Pcopy[s].size(); ++qP)
2448 auto qA =
A[g][
loc1][s].dict.find(quple);
2450 if (qA !=
A[g][
loc1][s].dict.end())
2454 addRight(Pcopy[s].block[qP],
A[g][
loc1][s].block[qA->second]);
2465 if (Pcopy[s].block[qP].rows() != inBasis(
loc1).inner_dim(quple[0]))
2467 addBottom(Eigen::Matrix<Scalar,-1,-1>::Zero(inBasis(
loc1).inner_dim(quple[0])-Pcopy[s].block[qP].rows(),Pcopy[s].block[qP].cols()),Pcopy[s].block[qP]);
2472 if (Pcopy[s].block[qP].cols() != outBasis(
loc1).inner_dim(quple[1]))
2474 addRight(Eigen::Matrix<Scalar,-1,-1>::Zero(Pcopy[s].block[qP].rows(),outBasis(
loc1).inner_dim(quple[1])-Pcopy[s].block[qP].cols()),Pcopy[s].block[qP]);
2477 A[g][
loc1][s].push_back(quple, Pcopy[s].block[qP]);
2482 for (
size_t s=0; s<
A[g][
loc1].size(); s++)
2483 for (
size_t qA=0; qA<
A[g][
loc1][s].size(); qA++)
2489 addRight(Eigen::Matrix<Scalar,-1,-1>::Zero(
A[g][
loc1][s].block[qA].rows(), expanded_base.
inner_dim(
A[g][
loc1][s].out[qA]) -
A[g][
loc1][s].block[qA].cols()),
A[g][
loc1][s].block[qA]);
2502 update_inbase(
loc1,g);
2503 update_outbase(
loc1,g);
2505 for (
const auto &[qval,qdim,plain]:base_P)
2506 for (
size_t s=0; s<locBasis(
loc2).size(); ++s)
2508 std::vector<qarray<Symmetry::Nq> > qins_outs;
2509 if (g ==
GAUGE::L) {qins_outs = Symmetry::reduceSilent(qval, locBasis(
loc2)[s]);}
2510 else if (g ==
GAUGE::R) {qins_outs = Symmetry::reduceSilent(qval, Symmetry::flip(locBasis(
loc2)[s]));}
2511 for (
const auto &qin_out:qins_outs)
2516 if (outBasis(
loc2).find(qin_out) ==
false) {
continue;}
2517 quple = {qval, qin_out};
2521 if (inBasis(
loc2).find(qin_out) ==
false) {
continue;}
2522 quple = {qin_out, qval};
2524 auto it =
A[g][
loc2][s].dict.find(quple);
2525 if (it !=
A[g][
loc2][s].dict.end())
2529 if (
A[g][
loc2][s].block[it->second].rows() != expanded_base.
inner_dim(quple[0]))
2531 addBottom(Eigen::Matrix<Scalar,-1,-1>::Zero(base_P.
inner_dim(qval),
A[g][
loc2][s].block[it->second].cols()),
A[g][
loc2][s].block[it->second]);
2536 if (
A[g][
loc2][s].block[it->second].cols() != expanded_base.
inner_dim(quple[1]))
2538 addRight(Eigen::Matrix<Scalar,-1,-1>::Zero(
A[g][
loc2][s].block[it->second].rows(),base_P.
inner_dim(qval)),
A[g][
loc2][s].block[it->second]);
2548 A[g][
loc2][s].push_back(quple, Mtmp);
2573template<
typename Symmetry,
typename Scalar>
2577 vector<vector<Biped<Symmetry,MatrixType> > > A_ortho(
N_sites);
2578 for (
size_t l=0; l<
N_sites; l++)
2580 A_ortho[l].resize(qloc[l].size());
2583 vector<Biped<Symmetry,MatrixType> > Rprev(
N_sites);
2588 vector<vector<Biped<Symmetry,MatrixType> > > AxR(
N_sites);
2589 for (
size_t loc=0; loc<
N_sites; loc++)
2591 AxR[loc].resize(qloc[loc].size());
2593 double tol = 1.e-10, err=1.;
2594 size_t i=0, imax = 10001;
2595 while (err >
tol and i < imax)
2597 for (
size_t loc=
N_sites-1; loc!=-1; --loc)
2599 for (
size_t s=0; s<qloc[loc].size(); s++)
2601 AxR[loc][s] =
A[g][loc][s] * Rprev[loc];
2606 for (
size_t q=0; q<A_blocked.dim; ++q)
2608 HouseholderQR<MatrixType> Quirinus;
2609 Quirinus.compute(A_blocked.block[q].adjoint());
2611 MatrixType Qmat = Quirinus.householderQ() * MatrixType::Identity(A_blocked.block[q].cols(),A_blocked.block[q].rows());
2612 MatrixType Rmat = MatrixType::Identity(A_blocked.block[q].rows(),A_blocked.block[q].cols()) * Quirinus.matrixQR().template triangularView<Upper>();
2614 DiagonalMatrix<Scalar,Dynamic> Sign = Rmat.diagonal().cwiseSign().matrix().asDiagonal();
2619 Q.
push_back(A_blocked.in[q], A_blocked.out[q], (Qmat.adjoint()));
2620 R.
push_back(A_blocked.in[q], A_blocked.out[q], Rmat.adjoint());
2623 if (loc>0) {Rprev[loc-1] = R;}
2633 lout <<
"Orhtogonalize right: iteration number=" << i <<
", err=" << err << endl << endl;
2638template<
typename Symmetry,
typename Scalar>
2642 vector<vector<Biped<Symmetry,MatrixType> > > A_ortho(
N_sites);
2643 for (
size_t l=0; l<
N_sites; l++)
2645 A_ortho[l].resize(qloc[l].size());
2648 vector<Biped<Symmetry,MatrixType> > Lprev(
N_sites);
2650 Lprev[0].
setRandom(inbase[0],inbase[0]);
2652 vector<vector<Biped<Symmetry,MatrixType> > > LxA(
N_sites);
2653 for (
size_t loc=0; loc<
N_sites; loc++)
2655 LxA[loc].resize(qloc[loc].size());
2657 double tol = 1.e-10, err=1.;
2658 size_t i=0, imax = 10001;
2659 while (err >
tol and i < imax)
2661 for (
size_t loc=0; loc<
N_sites; loc++)
2663 for (
size_t s=0; s<qloc[loc].size(); s++)
2665 LxA[loc][s] = Lprev[loc] *
A[g][loc][s];
2670 for (
size_t q=0; q<A_blocked.dim; ++q)
2672 HouseholderQR<MatrixType> Quirinus;
2673 Quirinus.compute(A_blocked.block[q]);
2675 MatrixType Qmat = Quirinus.householderQ() * MatrixType::Identity(A_blocked.block[q].rows(),A_blocked.block[q].cols());
2676 MatrixType Rmat = MatrixType::Identity(A_blocked.block[q].cols(),A_blocked.block[q].rows()) * Quirinus.matrixQR().template triangularView<Upper>();
2678 DiagonalMatrix<Scalar,Dynamic> Sign = Rmat.diagonal().cwiseSign().matrix().asDiagonal();
2683 Q.
push_back(A_blocked.in[q], A_blocked.out[q], Qmat);
2684 R.
push_back(A_blocked.in[q], A_blocked.out[q], Rmat);
2687 if (loc<
N_sites-1) {Lprev[loc+1] = R;}
2691 err = (Lnext - Lprev[0]).
norm();
2698 lout <<
"Orthogonalize left: iteration number=" << i <<
", err=" << err << endl << endl;
2701template<
typename Symmetry,
typename Scalar>
2707 vector<Biped<Symmetry,MatrixType> > U(
N_sites);
2708 vector<Biped<Symmetry,MatrixType> > Vdag(
N_sites);
2711 for (
size_t l=0; l<
N_sites; ++l)
2716 auto [trunc_U,Sigma,trunc_Vdag] = C[l].truncateSVD(min_Nsv,max_Nsv,this->eps_truncWeight,trunc,
true);
2718 Vdag[l] = trunc_Vdag;
2723 for (
size_t l=0; l<
N_sites; ++l)
2725 for (
size_t s=0; s<qloc[l].size(); ++s)
2739 for (
size_t l=0; l<
N_sites; ++l)
2741 C[l] = L[(l+1)%
N_sites] * C[l] * R[l];
2742 C[l] = C[l].sorted();
2749 for (
size_t l=0; l<
N_sites; l++)
2751 for (
size_t s=0; s<qloc[l].size(); ++s)
2754 if (SET_AC_RANDOM) {
A[
GAUGE::C][l][s].setRandom(); }
2762template<
typename Symmetry,
typename Scalar>
2769 complex<double> lambda1;
2786 RandBiped.
setRandom(inBasis(0), inBasis(0));
2792 RandBiped = 1./RandBiped.
norm() * RandBiped;
2798 John.set_dimK(dimK);
2800 John.calc_dominant(T,x);
2801 lout <<
"Fixed point(" << label <<
"): GAUGE=" << g <<
", DIR=" << DIR <<
": " << John.info() << endl;
2805 res[0].first = John.get_lambda(0);
2806 res[0].second = x.
data;
2808 for (
int n=0; n<N-1; ++n)
2810 res[n+1].first = John.get_lambda(n+1);
2811 res[n+1].second = John.get_excited(n).data;
2814 if (abs(lambda1.imag()) > 1e1*
tol)
2816 lout << John.info() << endl;
2817 lout << termcolor::red <<
"Non-zero imaginary part of dominant eigenvalue λ=" << lambda1 <<
", |λ|=" << abs(lambda1) << termcolor::reset << endl;
2820 lout <<
"norm test=" << x.
data.
norm() << endl;
2831 for (
int n=1; n<N; ++n)
2833 res[n].first = John.get_lambda(n);
2842template<
typename Symmetry,
typename Scalar>
2843template<
typename MpoScalar>
2850 complex<double> lambda1;
2868 Lid.
setIdentity(Obs.inBasis(0).inner_dim(Symmetry::qvacuum()), 1, inBasis(0));
2871 Rid.
setIdentity(Obs.outBasis(Obs.length()-1).inner_dim(Symmetry::qvacuum()), 1, outBasis(Obs.length()-1));
2881 for (
int l=
N_sites-2; l>=0; --l)
2884 TripodInitTmp = TripodInit;
2892 for (
size_t l=1; l<
N_sites; ++l)
2895 TripodInitTmp = TripodInit;
2902 if (dimK != -1) Arnie.set_dimK(dimK);
2903 Arnie.calc_dominant(T,x);
2904 lout <<
"Fixed point(" << label <<
"):" <<
" GAUGE=" << g <<
", DIR=" << DIR <<
": " << Arnie.info() << endl;
2906 res[0].first = Arnie.get_lambda(0);
2907 res[0].second = x.
data;
2909 for (
int n=0; n<N-1; ++n)
2911 res[n+1].first = Arnie.get_lambda(n+1);
2912 res[n+1].second = Arnie.get_excited(n).data;
2915 if (abs(lambda1.imag()) > 1e1*
tol)
2917 lout << Arnie.info() << endl;
2918 lout << termcolor::red <<
"Non-zero imaginary part of dominant eigenvalue λ=" << lambda1 <<
", |λ|=" << abs(lambda1) << termcolor::reset << endl;
2921 for (
int n=1; n<N; ++n)
2923 res[n].first = Arnie.get_lambda(n);
2932template<
typename Symmetry,
typename Scalar>
2937 complex<double> lambda;
2956 RandBiped.
setRandom(inBasis(0), inBasis(0));
2962 RandBiped = 1./RandBiped.
norm() * RandBiped;
2967 lout <<
"fixed point, gauge=" << g <<
", DIR=" << DIR <<
": " << John.info() << endl;
2973 lout << boolalpha <<
"TRANSPOSE=" << TRANSPOSE <<
", CONJUGATE=" << CONJUGATE << endl;
2974 lout << R.info() << endl;
2976 complex<double> O = (U.contract(U.conjugate())).trace();
2977 lout <<
"O raw result: " << O << endl;
2979 if (abs(abs(lambda)-1.)>1e-2) O=0.;
2980 lout << termcolor::blue <<
"O=" << O.real() << termcolor::reset << endl << endl;
2981 return std::make_pair(O,x.
data);
2984template<
typename Symmetry,
typename Scalar>
2989 complex<double> lambda1, lambda2;
3011 RandBiped.
setRandom(inBasis(0), inBasis(0));
3017 RandBiped = 1./RandBiped.
norm() * RandBiped;
3023 #pragma omp sections
3027 John.calc_dominant(T1,x1,lambda1);
3031 Jane.calc_dominant(T2,x2,lambda2);
3035 lout <<
"fixed point, gauge=" << g <<
", DIR=" << DIR <<
": " << John.info() << endl;
3036 lout <<
"fixed point, gauge=" << g <<
", DIR=" << DIR <<
": " << Jane.info() << endl;
3041 lout << R1.info() << endl;
3042 lout << R2.info() << endl;
3046 complex<double> O12 = (U1.contract(U2.contract(U1.adjoint().contract(U2.adjoint())))).trace();
3047 O12 *= double(U1.block[0].rows());
3049 lout <<
"O12 raw result=" << O12 << endl;
3051 lout <<
"commut=" << U1.block[0].rows()*(U1.block[0]*U2.block[0]-U2.block[0]*U1.block[0]).
norm() << endl;
3052 lout <<
"anticommut=" << U1.block[0].rows()*(U1.block[0]*U2.block[0]+U2.block[0]*U1.block[0]).
norm() << endl;
3054 if (abs(abs(lambda1)-1.)>1e-2 or abs(abs(lambda2)-1.)>1e-2) O12=0.;
3055 lout << termcolor::blue <<
"O12=" << O12.real() << termcolor::reset << endl << endl;
3056 return std::make_pair(O12,x1.
data);
3059template<
typename Symmetry,
typename Scalar>
3063 vector<pair<qarray<Nq>,
double> > Svals;
3064 for (
const auto &x : SVspec[loc])
3065 for (
int i=0; i<std::get<0>(x.second).size(); ++i)
3067 Svals.push_back(std::make_pair(x.first,std::get<0>(x.second)(i)));
3069 sort(Svals.begin(), Svals.end(), [] (
const pair<
qarray<Nq>,
double> &p1,
const pair<
qarray<Nq>,
double> &p2) { return p2.second < p1.second;});
3071 ArrayXd Sout(Svals.size());
3072 vector<qarray<Nq> > Qout(Svals.size());
3073 for (
int i=0; i<Svals.size(); ++i)
3075 Sout(i) = Svals[i].second;
3076 Qout[i] = Svals[i].first;
3078 return std::make_pair(Qout,Sout);
3081template<
typename Symmetry,
typename Scalar>
3082template<
typename MpoScalar>
3087 double t_LReigen=0.;
3089 double t_contraction=0.;
3091 Stopwatch<> TotTimer;
3095 Stopwatch<> LReigenTimer;
3106 t_LReigen += LReigenTimer.time();
3111 Stopwatch<> ContractionTimer;
3113 lout << Oalfa.
info() << endl;
3114 lout << Obeta.
info() << endl;
3121 vector<Tripod<Symmetry,Matrix<MpoScalar,Dynamic,Dynamic> > > bmalfaTripod(
N_sites);
3125 for (
size_t l=1; l<
N_sites; ++l)
3132 vector<Tripod<Symmetry,Matrix<MpoScalar,Dynamic,Dynamic> > > bpalfaTripod(
N_sites);
3136 for (
int l=
N_sites-2; l>=0; --l)
3141 assert(bpalfaTripod[0].size() > 0);
3144 vector<Tripod<Symmetry,Matrix<MpoScalar,Dynamic,Dynamic> > > bmbetaTripod(
N_sites);
3148 for (
int l=
N_sites-2; l>=0; --l)
3153 assert(bmbetaTripod[0].size() > 0);
3156 vector<Tripod<Symmetry,Matrix<MpoScalar,Dynamic,Dynamic> > > bpbetaTripod(
N_sites);
3160 for (
size_t l=1; l<
N_sites; ++l)
3175 t_contraction += ContractionTimer.time();
3177 ArrayXXcd out(kpoints,2);
3178 if (kmin==kmax) {out.resize(1,2);}
3181 Stopwatch<> GMRES_Timer;
3182 #pragma omp parallel for
3183 for (
int ik=0; ik<out.rows(); ++ik)
3186 double kval = (kmin==kmax)? kmin : kmin + ik*(kmax-kmin)/(kpoints-1);
3192 Gimli.set_dimK(min(100ul,
dim(bmalfa)));
3193 assert(
dim(bmalfa) > 0);
3195 Gimli.solve_linear(Tm, bmalfa, Fmalfa,
tol,
true);
3198 lout << ik <<
", k/Ï€=" << kval/M_PI <<
", term exp(-i*Lcell*k), " << Gimli.info() <<
"; dim(bmalfa)=" <<
dim(bmalfa) << endl;
3203 Gimli.set_dimK(min(100ul,
dim(bpalfa)));
3204 assert(
dim(bpalfa) > 0);
3206 Gimli.solve_linear(Tp, bpalfa, Fpalfa,
tol,
true);
3209 lout << ik <<
", k/Ï€=" << kval/M_PI <<
", term exp(+i*Lcell*k), " << Gimli.info() <<
"; dim(bpalfa)=" <<
dim(bpalfa) << endl;
3218 out(ik,1) = exp(-1.i*
static_cast<double>(Lx)*kval) * resm + exp(+1.i*
static_cast<double>(Lx)*kval) * resp;
3221 t_GMRES += GMRES_Timer.time();
3223 t_tot = TotTimer.time();
3227 lout << TotTimer.info(
"StructureFactor")
3228 <<
" (LReigen=" << round(t_LReigen/
t_tot*100.,0) <<
"%, "
3229 <<
"GMRES=" << round(t_GMRES/
t_tot*100.,0) <<
"%, "
3230 <<
"contractions=" << round(t_contraction/
t_tot*100.,0) <<
"%)"
3231 <<
", kmin/Ï€=" << kmin/M_PI <<
", kmax/Ï€=" << kmax/M_PI <<
", kpoints=" << out.rows() << endl;
3232 lout <<
"\t" << Oalfa.
info() << endl;
3233 lout <<
"\t" << Obeta.
info() << endl;
3239template<
typename Symmetry,
typename Scalar>
3240template<
typename MpoScalar>
3244 ArrayXXcd res = intercellSF(Oalfa, Obeta, Lx, kval, kval, 1, VERB);
3248template<
typename Symmetry,
typename Scalar>
3249template<
typename MpoScalar>
3254 assert(Oalfa.size() == Lx and Obeta.size() == Lx and cellAvg.rows() == Lx and cellAvg.cols() == Lx);
3256 complex<double> res = 0;
3258 ArrayXXcd Sijk = cellAvg;
3260 #ifndef UMPS_DONT_PARALLELIZE_SF_LOOPS
3261 #pragma omp parallel for collapse(2)
3263 for (
size_t i0=0; i0<Lx; ++i0)
3264 for (
size_t j0=0; j0<Lx; ++j0)
3266 Sijk(i0,j0) += intercellSFpoint(Oalfa[i0],Obeta[j0], Lx, kval, VERB);
3269 for (
size_t i0=0; i0<Lx; ++i0)
3270 for (
size_t j0=0; j0<Lx; ++j0)
3273 res += 1./
static_cast<double>(Lx) * exp(-1.i*kval*(
static_cast<double>(i0)-
static_cast<double>(j0))) * Sijk(j0,i0);
3280template<
typename Symmetry,
typename Scalar>
3281template<
typename MpoScalar>
3286 assert(Oalfa.size() == Lx and Obeta.size() == Lx and cellAvg.rows() == Lx and cellAvg.cols() == Lx);
3288 vector<vector<ArrayXXcd> > Sijk(Lx);
3289 for (
size_t i0=0; i0<Lx; ++i0)
3291 Sijk[i0].resize(Lx);
3292 for (
size_t j0=0; j0<Lx; ++j0)
3294 Sijk[i0][j0].resize(kpoints,2);
3299 #ifndef UMPS_DONT_PARALLELIZE_SF_LOOPS
3300 #pragma omp parallel for collapse(2)
3302 for (
size_t i0=0; i0<Lx; ++i0)
3303 for (
size_t j0=0; j0<Lx; ++j0)
3305 Sijk[i0][j0] = intercellSF(Oalfa[i0],Obeta[j0],Lx,kmin,kmax,kpoints,VERB,
tol);
3306 Sijk[i0][j0].col(1) += cellAvg(i0,j0);
3309 ArrayXXcd res(kpoints,2); res=0;
3311 for (
size_t ik=0; ik<kpoints; ++ik)
3312 for (
size_t i0=0; i0<Lx; ++i0)
3313 for (
size_t j0=0; j0<Lx; ++j0)
3315 double kval = Sijk[i0][j0](ik,0).real();
3319 res(ik,1) += 1./
static_cast<double>(Lx) * exp(-1.i*kval*(
static_cast<double>(i0)-
static_cast<double>(j0))) * Sijk[j0][i0](ik,1);
void addBottom(const MatrixType1 &Min, MatrixType2 &Mout)
void addRight(const MatrixType1 &Min, MatrixType2 &Mout)
void contract_AW(const vector< Biped< Symmetry, Matrix< Scalar, Dynamic, Dynamic > > > &Ain, const vector< qarray< Symmetry::Nq > > &qloc, const vector< vector< vector< Biped< Symmetry, MpoMatrixType > > > > &W, const vector< qarray< Symmetry::Nq > > &qOp, const Qbasis< Symmetry > &qauxAl, const Qbasis< Symmetry > &qauxWl, const Qbasis< Symmetry > &qauxAr, const Qbasis< Symmetry > &qauxWr, vector< Biped< Symmetry, Matrix< Scalar, Dynamic, Dynamic > > > &Aout, bool FORCE_QTOT=false, qarray< Symmetry::Nq > Qtot=Symmetry::qvacuum())
Hamiltonian sum(const Hamiltonian &H1, const Hamiltonian &H2, DMRG::VERBOSITY::OPTION VERBOSITY=DMRG::VERBOSITY::SILENT)
Mpo< Symmetry, Scalar > diff(const Mpo< Symmetry, Scalar > &H1, const Mpo< Symmetry, Scalar > &H2, DMRG::VERBOSITY::OPTION VERBOSITY=DMRG::VERBOSITY::SILENT)
double norm(const PivotMatrix0< Symmetry, Scalar, MpoScalar > &H)
size_t dim(const PivotMatrix0< Symmetry, Scalar, MpoScalar > &H)
double squaredNorm(const PivotVector< Symmetry, Scalar_ > &V)
vector< vector< Biped< Symmetry, Matrix< complex< Scalar >, Dynamic, Dynamic > > > > apply_symm(const vector< vector< Biped< Symmetry, Matrix< complex< Scalar >, Dynamic, Dynamic > > > > &A, const Mpo< Symmetry, complex< Scalar > > &R, const vector< vector< qarray< Symmetry::Nq > > > &qloc, const vector< Qbasis< Symmetry > > &qauxAl, const vector< Qbasis< Symmetry > > &qauxAr, bool TRANSPOSE=false, bool CONJUGATE=false)
Eigenstate< Biped< Symmetry, Matrix< complex< Scalar >, Dynamic, Dynamic > > > calc_LReigen(VMPS::DIRECTION::OPTION DIR, const vector< vector< Biped< Symmetry, Matrix< Scalar, Dynamic, Dynamic > > > > &Abra, const vector< vector< Biped< Symmetry, Matrix< Scalar, Dynamic, Dynamic > > > > &Aket, const Qbasis< Symmetry > &basisBra, const Qbasis< Symmetry > &basisKet, const vector< vector< qarray< Symmetry::Nq > > > &qloc, size_t dimK=100ul, double tol_input=1e-12, Biped< Symmetry, Matrix< Scalar, Dynamic, Dynamic > > *LReigenTop=NULL)
Biped< Symmetry, MatrixType > Aclump(DMRG::DIRECTION::OPTION DIR)
vector< Biped< Symmetry, MatrixType > > reblock(const Biped< Symmetry, MatrixType > &B, DMRG::DIRECTION::OPTION DIR)
const std::vector< std::vector< std::vector< Biped< Symmetry, MatrixType > > > > & W_at(const std::size_t loc) const
const std::vector< std::vector< qType > > & locBasis() const
void transform_base(const qType &qShift, const bool PRINT=false, const int factor=-1, const std::size_t powre=0ul)
const std::vector< std::vector< qType > > & opBasis() const
std::string info(bool REDUCED=false) const
Matrix< Scalar, Dynamic, Dynamic > MatrixType
double memory(MEMUNIT memunit=GB) const
Eigen::Index leftAmount(const qType &qnew, const std::array< qType, 2 > &qold) const
qType find(const std::string &ident) const
Qbasis< Symmetry > combine(const Qbasis< Symmetry > &other, bool FLIP=false) const
Qbasis< Symmetry > add(const Qbasis< Symmetry > &other) const
void pullData(const vector< Biped< Symmetry, MatrixType > > &A, const Eigen::Index &leg)
std::unordered_map< qType, std::vector< fuseData > > history
Eigen::Index inner_dim(const Eigen::Index &num_in) const
qarray< Symmetry::Nq > Qtop(size_t loc) const
qarray< Symmetry::Nq > Qbot(size_t loc) const
double dot(const Umps< Symmetry, Scalar > &Vket) const
Umps< Symmetry, OtherScalar > cast() const
vector< qarray< Symmetry::Nq > > locBasis(size_t loc) const
vector< vector< qarray< Symmetry::Nq > > > qloc
const vector< Biped< Symmetry, MatrixType > > & A_at(GAUGE::OPTION g, size_t loc) const
void graph(string filename) const
size_t get_frst_rows() const
void calc_N(DMRG::DIRECTION::OPTION DIR, size_t loc, vector< Biped< Symmetry, MatrixType > > &N) const
vector< map< qarray< Nq >, tuple< ArrayXd, int > > > entanglementSpectrum() const
void calc_entropy(bool PRINT=false)
Umps< Symmetry, double > real() const
Qbasis< Symmetry > inBasis(size_t loc) const
vector< Qbasis< Symmetry > > inbase
void svdDecompose(size_t loc, GAUGE::OPTION gauge=GAUGE::C)
ArrayXXcd intercellSF(const Mpo< Symmetry, MpoScalar > &Oalfa, const Mpo< Symmetry, MpoScalar > &Obeta, int Lx, double kmin=0., double kmax=2.*M_PI, int kpoints=51, DMRG::VERBOSITY::OPTION VERB=DMRG::VERBOSITY::ON_EXIT, double tol=1e-12)
void truncate(bool SET_AC_RANDOM=true)
vector< Qbasis< Symmetry > > outBasis() const
void polarDecompose(size_t loc, GAUGE::OPTION gauge=GAUGE::C)
static constexpr size_t Nq
double memory(MEMUNIT memunit) const
size_t calc_Nqmax() const
void calc_entropy(size_t loc, bool PRINT=false)
qarray< Nq > Qtarget() const
size_t calc_fullMmax() const
Qbasis< Symmetry > outBasis(size_t loc) const
void update_inbase(GAUGE::OPTION g=GAUGE::C)
vector< map< qarray< Nq >, tuple< ArrayXd, int > > > SVspec
void enrich(size_t loc, GAUGE::OPTION g, const vector< Biped< Symmetry, MatrixType > > &P)
void adjustQN(const size_t number_cells)
Scalar calc_epsLRsq(GAUGE::OPTION gauge, size_t loc) const
size_t get_last_cols() const
vector< std::pair< complex< double >, Tripod< Symmetry, Matrix< complex< double >, Dynamic, Dynamic > > > > calc_dominant_Q(const Mpo< Symmetry, MpoScalar > &O, GAUGE::OPTION g=GAUGE::R, DMRG::DIRECTION::OPTION DIR=DMRG::DIRECTION::RIGHT, int N=2, double tol=1e-15, int dimK=-1, string label="") const
size_t minus1modL(size_t l) const
ArrayXXcd SF(const ArrayXXcd &cellAvg, const vector< Mpo< Symmetry, MpoScalar > > &Oalfa, const vector< Mpo< Symmetry, MpoScalar > > &Obeta, int Lx, double kmin, double kmax, int kpoints, DMRG::VERBOSITY::OPTION VERB=DMRG::VERBOSITY::ON_EXIT, double tol=1e-12)
string test_ortho(double tol=1e-6) const
void updateAC(size_t loc, GAUGE::OPTION g)
void update_inbase(size_t loc, GAUGE::OPTION g=GAUGE::C)
void resize(size_t Mmax_input, size_t Nqmax_input, bool INIT_TO_HALF_INTEGER_SPIN)
void orthogonalize_right(GAUGE::OPTION g, vector< Biped< Symmetry, MatrixType > > &G_R)
std::array< vector< vector< Biped< Symmetry, MatrixType > > >, 3 > A
vector< Qbasis< Symmetry > > outbase
complex< Scalar > intercellSFpoint(const Mpo< Symmetry, MpoScalar > &Oalfa, const Mpo< Symmetry, MpoScalar > &Obeta, int Lx, double kval, DMRG::VERBOSITY::OPTION VERB=DMRG::VERBOSITY::ON_EXIT)
vector< std::pair< complex< double >, Biped< Symmetry, Matrix< complex< double >, Dynamic, Dynamic > > > > calc_dominant(GAUGE::OPTION g=GAUGE::R, DMRG::DIRECTION::OPTION DIR=DMRG::DIRECTION::RIGHT, int N=2, double tol=1e-15, int dimK=-1, qarray< Symmetry::Nq > Qtot=Symmetry::qvacuum(), string label="") const
complex< Scalar > SFpoint(const ArrayXXcd &cellAvg, const vector< Mpo< Symmetry, MpoScalar > > &Oalfa, const vector< Mpo< Symmetry, MpoScalar > > &Obeta, int Lx, double kval, DMRG::VERBOSITY::OPTION VERB=DMRG::VERBOSITY::ON_EXIT)
void update_outbase(GAUGE::OPTION g=GAUGE::C)
vector< Qbasis< Symmetry > > inBasis() const
std::pair< vector< qarray< Symmetry::Nq > >, ArrayXd > entanglementSpectrumLoc(size_t loc) const
void update_outbase(size_t loc, GAUGE::OPTION g=GAUGE::C)
vector< Biped< Symmetry, MatrixType > > C
std::pair< complex< double >, Biped< Symmetry, Matrix< complex< double >, Dynamic, Dynamic > > > calc_dominant_2symm(GAUGE::OPTION g, DMRG::DIRECTION::OPTION DIR, const Mpo< Symmetry, complex< double > > &R1, const Mpo< Symmetry, complex< double > > &R2) const
void sort_A(size_t loc, GAUGE::OPTION g, bool SORT_ALL_GAUGES=false)
vector< vector< qarray< Symmetry::Nq > > > locBasis() const
void orthogonalize_left(GAUGE::OPTION g, vector< Biped< Symmetry, MatrixType > > &G_L)
Matrix< Scalar, Dynamic, Dynamic > MatrixType
std::pair< complex< double >, Biped< Symmetry, Matrix< complex< double >, Dynamic, Dynamic > > > calc_dominant_1symm(GAUGE::OPTION g, DMRG::DIRECTION::OPTION DIR, const Mpo< Symmetry, complex< double > > &R, bool TRANSPOSE, bool CONJUGATE) const
void contract_R(const Tripod< Symmetry, MatrixType2 > &Rold, const vector< Biped< Symmetry, MatrixType > > &Abra, const vector< vector< vector< Biped< Symmetry, MpoMatrixType > > > > &W, const vector< Biped< Symmetry, MatrixType > > &Aket, const vector< qarray< Symmetry::Nq > > &qloc, const vector< qarray< Symmetry::Nq > > &qOp, Tripod< Symmetry, MatrixType2 > &Rnew, bool RANDOMIZE=false, tuple< CONTRACT_LR_MODE, size_t > MODE_input=make_pair(FULL, 0), const std::unordered_map< pair< qarray< Symmetry::Nq >, size_t >, size_t > &basis_order_map={})
void contract_L(const Tripod< Symmetry, MatrixType2 > &Lold, const vector< Biped< Symmetry, MatrixType > > &Abra, const vector< vector< vector< Biped< Symmetry, MpoMatrixType > > > > &W, const vector< Biped< Symmetry, MatrixType > > &Aket, const vector< qarray< Symmetry::Nq > > &qloc, const vector< qarray< Symmetry::Nq > > &qOp, Tripod< Symmetry, MatrixType2 > &Lnew, bool RANDOMIZE=false, tuple< CONTRACT_LR_MODE, size_t > MODE_input=make_pair(FULL, 0), const std::unordered_map< pair< qarray< Symmetry::Nq >, size_t >, size_t > &basis_order_map={})
Scalar contract_LR(const Tripod< Symmetry, Matrix< Scalar, Dynamic, Dynamic > > &L, const vector< Biped< Symmetry, Matrix< Scalar, Dynamic, Dynamic > > > &Abra, const vector< vector< vector< Biped< Symmetry, MpoMatrixType > > > > &W, const vector< Biped< Symmetry, Matrix< Scalar, Dynamic, Dynamic > > > &Aket, const Tripod< Symmetry, Matrix< Scalar, Dynamic, Dynamic > > &R, const vector< qarray< Symmetry::Nq > > &qloc, const vector< qarray< Symmetry::Nq > > &qOp)
std::array< qarray< Nq >, 2 > qarray2
Biped< Symmetry, MatrixType_ > adjoint() const
std::vector< MatrixType_ > block
void push_back(qType qin, qType qout, const MatrixType_ &M)
double operatorNorm(bool COLWISE=true) const
std::vector< std::vector< std::vector< std::vector< Biped< Symmetry, MatrixType > > > > > W
Tripod< Symmetry, Matrix< Scalar, Dynamic, Dynamic > > data
void setIdentity(size_t Drows, size_t Dcols, size_t amax=1, size_t bmax=1)
Biped< Symmetry, Matrix< Scalar_, Dynamic, Dynamic > > data