1#ifndef STRAWBERRY_DMRGCONTRACTIONS_WITH_Q
2#define STRAWBERRY_DMRGCONTRACTIONS_WITH_Q
5#include <unordered_set>
34template<
typename Symmetry,
typename MatrixType,
typename MatrixType2,
typename MpoMatrixType>
42 bool RANDOMIZE =
false,
43 tuple<CONTRACT_LR_MODE,size_t> MODE_input = make_pair(
FULL,0),
48 auto [
MODE,fixed_ab] = MODE_input;
50 #ifdef DMRG_CONTRACTLANDR_PARALLELIZE
51 #pragma omp parallel for collapse(3) schedule(dynamic)
53 for (
size_t s1=0; s1<qloc.size(); ++s1)
54 for (
size_t s2=0; s2<qloc.size(); ++s2)
55 for (
size_t k=0; k<qOp.size(); ++k)
57 typename MpoMatrixType::Scalar factor_cgc;
60 for (
size_t qL=0; qL<Lold.
dim; ++qL)
62 vector<tuple<qarray3<Symmetry::Nq>,size_t,size_t,
size_t> > ix;
63 bool FOUND_MATCH =
LAWA(Lold.
in(qL), Lold.
out(qL), Lold.
mid(qL), qloc[s1], qloc[s2], qOp[k], Abra[s1], Aket[s2], W[s1][s2][k], ix);
67 for(
size_t n=0; n<ix.size(); n++ )
70 swap(quple[0], quple[1]);
71 size_t qAbra = get<1>(ix[n]);
72 size_t qAket = get<2>(ix[n]);
73 size_t qW = get<3>(ix[n]);
75 if (Aket[s2].block[qAket].size() == 0) {
continue;}
76 if (Abra[s1].block[qAbra].size() == 0) {
continue;}
78 if constexpr ( Symmetry::NON_ABELIAN )
80 factor_cgc = Symmetry::coeff_buildL(Aket[s2].in[qAket], qloc[s2], Aket[s2].out[qAket],
81 Lold.
mid(qL), qOp[k], quple[2],
82 Abra[s1].in[qAbra], qloc[s1], Abra[s1].out[qAbra]);
89 if (abs(factor_cgc) < ::mynumeric_limits<double>::epsilon()) {
continue;}
91 for (
int r=0; r<W[s1][s2][k].block[qW].outerSize(); ++r)
92 for (
typename MpoMatrixType::InnerIterator iW(W[s1][s2][k].block[qW],r); iW; ++iW)
101 (MODE ==
TRIANGULAR and basis_order_map.at(make_pair(Lold.
mid(qL),a))>fixed_ab) or
102 (MODE ==
FIXED_COLS and basis_order_map.at(make_pair(quple[2],b))==fixed_ab) or
103 (MODE ==
FIXED_ROWS and basis_order_map.at(make_pair(Lold.
mid(qL),a))==fixed_ab)
112 if (Lold.
block[qL][a][0].size() != 0)
117 Mtmp.resize(Abra[s1].block[qAbra].cols(), Aket[s2].block[qAket].cols());
123 Abra[s1].block[qAbra].adjoint(),
124 Lold.
block[qL][a][0],
125 Aket[s2].block[qAket],
131 auto it = Lnew.
dict.find(quple);
132 if (it != Lnew.
dict.end())
134 if (Lnew.
block[it->second][b][0].rows() != Mtmp.rows() or
135 Lnew.
block[it->second][b][0].cols() != Mtmp.cols())
137 Lnew.
block[it->second][b][0] = Mtmp;
141 Lnew.
block[it->second][b][0] += Mtmp;
146 boost::multi_array<MatrixType2,LEGLIMIT> Mtmpvec(boost::extents[W[s1][s2][k].block[qW].cols()][1]);
147 Mtmpvec[b][0] = Mtmp;
179template<
typename Symmetry,
typename MatrixType,
typename MatrixType2,
typename MpoMatrixType>
187 bool RANDOMIZE =
false,
188 tuple<CONTRACT_LR_MODE,size_t> MODE_input = make_pair(
FULL,0),
193 auto [
MODE,fixed_ab] = MODE_input;
195 #ifdef DMRG_CONTRACTLANDR_PARALLELIZE
196 #pragma omp parallel for collapse(3) schedule(dynamic)
198 for (
size_t s1=0; s1<qloc.size(); ++s1)
199 for (
size_t s2=0; s2<qloc.size(); ++s2)
200 for (
size_t k=0; k<qOp.size(); ++k)
202 typename MpoMatrixType::Scalar factor_cgc;
205 for (
size_t qR=0; qR<Rold.
dim; ++qR)
207 vector<tuple<qarray3<Symmetry::Nq>,size_t,size_t,
size_t> > ix;
209 bool FOUND_MATCH =
AWAR(Rold.
in(qR), Rold.
out(qR), Rold.
mid(qR), qloc[s1], qloc[s2], qOp[k], Abra[s1], Aket[s2], W[s1][s2][k], ix);
213 for(
size_t n=0; n<ix.size(); n++ )
216 swap(quple[0], quple[1]);
217 size_t qAbra = get<1>(ix[n]);
218 size_t qAket = get<2>(ix[n]);
219 size_t qW = get<3>(ix[n]);
221 if (Aket[s2].block[qAket].size() == 0) {
continue;}
222 if (Abra[s1].block[qAbra].size() == 0) {
continue;}
224 if constexpr (Symmetry::NON_ABELIAN)
226 factor_cgc = Symmetry::coeff_buildR(Aket[s2].in[qAket], qloc[s2], Aket[s2].out[qAket],
227 quple[2] , qOp[k], Rold.
mid(qR),
228 Abra[s1].in[qAbra], qloc[s1], Abra[s1].out[qAbra]);
234 if (abs(factor_cgc) < ::mynumeric_limits<double>::epsilon()) {
continue;}
236 for (
int r=0; r<W[s1][s2][k].block[qW].outerSize(); ++r)
237 for (
typename MpoMatrixType::InnerIterator iW(W[s1][s2][k].block[qW],r); iW; ++iW)
246 (MODE ==
TRIANGULAR and fixed_ab>basis_order_map.at(make_pair(Rold.
mid(qR),b))) or
247 (MODE ==
FIXED_ROWS and basis_order_map.at(make_pair(quple[2],a))==fixed_ab) or
248 (MODE ==
FIXED_COLS and basis_order_map.at(make_pair(Rold.
mid(qR),b))==fixed_ab)
257 if (Rold.
block[qR][b][0].rows() != 0)
262 Mtmp.resize(Aket[s2].block[qAket].rows(), Abra[s1].block[qAbra].rows());
276 Aket[s2].block[qAket],
277 Rold.
block[qR][b][0],
278 Abra[s1].block[qAbra].adjoint(),
284 auto it = Rnew.
dict.find(quple);
285 if (it != Rnew.
dict.end())
287 if (Rnew.
block[it->second][a][0].rows() != Mtmp.rows() or
288 Rnew.
block[it->second][a][0].cols() != Mtmp.cols())
290 Rnew.
block[it->second][a][0] = Mtmp;
294 Rnew.
block[it->second][a][0] += Mtmp;
299 boost::multi_array<MatrixType2,LEGLIMIT> Mtmpvec(boost::extents[W[s1][s2][k].block[qW].rows()][1]);
300 Mtmpvec[a][0] = Mtmp;
327template<
typename Symmetry,
typename MatrixType,
typename MpoScalar>
336 MpoScalar factor_cgc;
340 for (
size_t s1=0; s1<qloc.size(); ++s1)
341 for (
size_t s2=0; s2<qloc.size(); ++s2)
342 for (
size_t k=0; k<qOp.size(); ++k)
345 for (
size_t qL=0; qL<Lold.
dim; ++qL)
347 vector<tuple<qarray3<Symmetry::Nq>,size_t,
size_t> > ix;
348 bool FOUND_MATCH =
LAWA(Lold.
in(qL), Lold.
out(qL), Lold.
mid(qL), s1, s2, qloc, k, qOp, Abra, Aket, ix);
350 if (FOUND_MATCH ==
true)
352 for(
size_t n=0; n<ix.size(); n++ )
355 swap(quple[0], quple[1]);
356 size_t qAbra = get<1>(ix[n]);
357 size_t qAket = get<2>(ix[n]);
358 if constexpr ( Symmetry::NON_ABELIAN )
360 factor_cgc = Symmetry::coeff_buildL(Aket[s2].in[qAket], qloc[s2], Aket[s2].out[qAket],
361 Lold.
mid(qL), qOp[k], quple[2],
362 Abra[s1].in[qAbra], qloc[s1], Abra[s1].out[qAbra]);
368 if (std::abs(factor_cgc) < ::mynumeric_limits<double>::epsilon()) {
continue; }
369 auto key = make_tuple(s1,s2,k,Lold.
mid(qL),quple[2]);
370 if(
auto it=V.find(key); it == V.end()) {
continue; }
371 for (
int r=0; r<V.at(key).outerSize(); ++r)
372 for (
typename SparseMatrix<MpoScalar>::InnerIterator iW(V.at(key),r); iW; ++iW)
374 size_t a1 = iW.row();
375 size_t a2 = iW.col();
376 if (Lold.
block[qL][a1][0].size() != 0)
380 Abra[s1].block[qAbra].adjoint(),
381 Lold.
block[qL][a1][0],
382 Aket[s2].block[qAket],
386 auto it = Lnew.
dict.find(quple);
387 if (it != Lnew.
dict.end())
389 if (Lnew.
block[it->second][a2][0].rows() != Mtmp.rows() or
390 Lnew.
block[it->second][a2][0].cols() != Mtmp.cols())
392 Lnew.
block[it->second][a2][0] = Mtmp;
396 Lnew.
block[it->second][a2][0] += Mtmp;
406 boost::multi_array<MatrixType,LEGLIMIT> Mtmpvec(boost::extents[V.at(key).cols()][1]);
407 Mtmpvec[a2][0] = Mtmp;
432template<
typename Symmetry,
typename MatrixType,
typename MpoScalar>
441 MpoScalar factor_cgc;
445 for (
size_t s1=0; s1<qloc.size(); ++s1)
446 for (
size_t s2=0; s2<qloc.size(); ++s2)
447 for (
size_t k=0; k<qOp.size(); ++k)
451 for (
size_t qR=0; qR<Rold.
dim; ++qR)
453 auto qRouts = Symmetry::reduceSilent(Rold.
out(qR),Symmetry::flip(qloc[s1]));
454 auto qRins = Symmetry::reduceSilent(Rold.
in(qR),Symmetry::flip(qloc[s2]));
456 for(
const auto& qRout : qRouts)
457 for(
const auto& qRin : qRins)
462 auto q1 = Abra[s1].dict.find(cmp1);
463 auto q2 = Aket[s2].dict.find(cmp2);
465 if (q1!=Abra[s1].dict.end() and
466 q2!=Aket[s2].dict.end())
470 auto qRmids = Symmetry::reduceSilent(Rold.
mid(qR),Symmetry::flip(qOp[k]));
472 for(
const auto& new_qmid : qRmids)
475 if constexpr (Symmetry::NON_ABELIAN)
477 factor_cgc = Symmetry::coeff_buildR(Aket[s2].in[q2->second], qloc[s2], Aket[s2].out[q2->second],
478 quple[2] , qOp[k], Rold.
mid(qR),
479 Abra[s1].in[q1->second], qloc[s1], Abra[s1].out[q1->second]);
485 if (std::abs(factor_cgc) < ::mynumeric_limits<double>::epsilon()) {
continue; }
486 auto key = make_tuple(s1,s2,k,quple[2],Rold.
mid(qR));
487 if(
auto it=V.find(key); it == V.end()) {
continue; }
488 for (
int r=0; r<V.at(key).outerSize(); ++r)
489 for (
typename SparseMatrix<MpoScalar>::InnerIterator iW(V.at(key),r); iW; ++iW)
491 size_t a1 = iW.row();
492 size_t a2 = iW.col();
494 if (Rold.
block[qR][a2][0].rows() != 0)
498 Aket[s2].block[q2->second],
499 Rold.
block[qR][a2][0],
500 Abra[s1].block[q1->second].adjoint(),
504 auto it = Rnew.
dict.find(quple);
505 if (it != Rnew.
dict.end())
507 if (Rnew.
block[it->second][a1][0].rows() != Mtmp.rows() or
508 Rnew.
block[it->second][a1][0].cols() != Mtmp.cols())
510 Rnew.
block[it->second][a1][0] = Mtmp;
514 Rnew.
block[it->second][a1][0] += Mtmp;
524 boost::multi_array<MatrixType,LEGLIMIT> Mtmpvec(boost::extents[V.at(key).rows()][1]);
525 Mtmpvec[a1][0] = Mtmp;
537template<
typename Symmetry,
typename MatrixType,
typename MatrixType2>
543 bool RANDOMIZE =
false,
556 for (
size_t s=0; s<qloc.size(); ++s)
557 for (
size_t qL=0; qL<Lold.
dim; ++qL)
559 vector<tuple<qarray2<Symmetry::Nq>,size_t,
size_t> > ix;
560 bool FOUND_MATCH =
LAA(Lold.
in[qL], Lold.
out[qL], s, qloc, Abra, Aket, ix);
564 for (
size_t n=0; n<ix.size(); n++)
567 swap(quple[0], quple[1]);
568 if (!Symmetry::validate(quple)) {
continue;}
569 size_t qAbra = get<1>(ix[n]);
570 size_t qAket = get<2>(ix[n]);
572 if (Lold.
block[qL].rows() != 0)
577 Mtmp.resize(Abra[s].block[qAbra].cols(), Aket[s].block[qAket].cols());
591 Abra[s].block[qAbra].adjoint(),
593 Aket[s].block[qAket],
597 auto it = Lnew.
dict.find(quple);
598 if (it != Lnew.
dict.end())
600 if (Lnew.
block[it->second].rows() != Mtmp.rows() or
601 Lnew.
block[it->second].cols() != Mtmp.cols())
603 Lnew.
block[it->second] = Mtmp;
607 Lnew.
block[it->second] += Mtmp;
620template<
typename Symmetry,
typename MatrixType,
typename MatrixType2>
626 bool RANDOMIZE =
false,
639 for (
size_t s=0; s<qloc.size(); ++s)
640 for (
size_t qR=0; qR<Rold.
dim; ++qR)
642 vector<tuple<qarray2<Symmetry::Nq>,size_t,
size_t> > ix;
643 bool FOUND_MATCH =
AAR(Rold.
in[qR], Rold.
out[qR], s, qloc, Abra, Aket, ix);
647 for (
size_t n=0; n<ix.size(); n++)
650 swap(quple[0], quple[1]);
651 if (!Symmetry::validate(quple)) {
continue;}
652 size_t qAbra = get<1>(ix[n]);
653 size_t qAket = get<2>(ix[n]);
655 double factor_cgc = Symmetry::coeff_rightOrtho(Abra[s].out[qAbra],
658 if (Rold.
block[qR].rows() != 0)
663 Mtmp.resize(Aket[s].block[qAket].rows(), Abra[s].block[qAbra].rows());
669 Aket[s].block[qAket],
671 Abra[s].block[qAbra].adjoint(),
675 auto it = Rnew.
dict.find(quple);
676 if (it != Rnew.
dict.end())
678 if (Rnew.
block[it->second].rows() != Mtmp.rows() or
679 Rnew.
block[it->second].cols() != Mtmp.cols())
681 Rnew.
block[it->second] = Mtmp;
685 Rnew.
block[it->second] += Mtmp;
759template<
typename Symmetry,
typename Scalar,
typename MpoMatrixType>
761 const vector<
Biped<Symmetry,Matrix<Scalar,Dynamic,Dynamic> > > &Abra,
763 const vector<
Biped<Symmetry,Matrix<Scalar,Dynamic,Dynamic> > > &Aket,
764 const Tripod<Symmetry,Matrix<Scalar,Dynamic,Dynamic> > &R,
767 Biped<Symmetry,Matrix<Scalar,Dynamic,Dynamic> > &Tout,
770 #ifdef DMRG_PARALLELIZE_GRALF
771 #pragma omp parallel for collapse(3) schedule(dynamic)
773 for (
size_t s1=0; s1<qloc.size(); ++s1)
774 for (
size_t s2=0; s2<qloc.size(); ++s2)
775 for (
size_t k=0; k<qOp.size(); ++k)
777 std::array<typename Symmetry::qType,3> qCheck;
778 Scalar factor_cgc, factor_merge;
780 qCheck = {qloc[s2],qOp[k],qloc[s1]};
781 if(!Symmetry::validate(qCheck)) {
continue;}
783 for (
size_t qL=0; qL<L.dim; ++qL)
785 vector<tuple<qarray3<Symmetry::Nq>,size_t,size_t,
size_t> > ix;
786 bool FOUND_MATCH =
LAWA(L.in(qL), L.out(qL), L.mid(qL), qloc[s1], qloc[s2], qOp[k], Abra[s1], Aket[s2], W[s1][s2][k], ix);
788 if (FOUND_MATCH ==
true)
790 for(
size_t n=0; n<ix.size(); n++ )
793 auto qR = R.dict.find(quple);
795 if (qR != R.dict.end())
797 swap(quple[0], quple[1]);
798 size_t qAbra = get<1>(ix[n]);
799 size_t qAket = get<2>(ix[n]);
800 size_t qW = get<3>(ix[n]);
801 if (Aket[s2].block[qAket].size() == 0) {
continue;}
802 if (Abra[s1].block[qAbra].size() == 0) {
continue;}
803 if constexpr (Symmetry::NON_ABELIAN)
807 factor_cgc = Symmetry::coeff_buildL(Aket[s2].in[qAket], qloc[s2], Aket[s2].out[qAket],
808 L.mid(qL) , qOp[k] , quple[2],
809 Abra[s1].in[qAbra], qloc[s1], Abra[s1].out[qAbra]);
811 factor_merge = Symmetry::coeff_rightOrtho(Abra[s1].out[qAbra],
812 Aket[s2].out[qAket]);
816 factor_cgc = Symmetry::coeff_buildR(Aket[s2].in[qAket], qloc[s2], Aket[s2].out[qAket],
817 L.mid(qL) , qOp[k] , quple[2],
818 Abra[s1].in[qAbra], qloc[s1], Abra[s1].out[qAbra]);
819 factor_merge = Symmetry::coeff_rightOrtho(L.in(qL),
828 if (std::abs(factor_cgc*factor_merge) < ::mynumeric_limits<Scalar>::epsilon()) {
continue;}
830 for (
int r=0; r<W[s1][s2][k].block[qW].outerSize(); ++r)
831 for (
typename MpoMatrixType::InnerIterator iW(W[s1][s2][k].block[qW],r); iW; ++iW)
833 size_t a1 = iW.row();
834 size_t a2 = iW.col();
836 if (L.block[qL][a1][0].size() != 0 and
837 R.block[qR->second][a2][0].size() != 0)
839 Matrix<Scalar,Dynamic,Dynamic> Mtmp;
844 R.block[qR->second][a2][0],
845 Abra[s1].block[qAbra].adjoint(),
847 Aket[s2].block[qAket],
854 Aket[s2].block[qAket],
855 R.block[qR->second][a2][0],
856 Abra[s1].block[qAbra].adjoint(),
864 qTout = {Aket[s2].out[qAket], Aket[s2].out[qAket]};
868 qTout = {Aket[s2].in[qAket], Aket[s2].in[qAket]};
872 auto it = Tout.dict.find(qTout);
873 if (it != Tout.dict.end())
875 if (Tout.block[it->second].rows() != Mtmp.rows() or
876 Tout.block[it->second].cols() != Mtmp.cols())
878 Tout.block[it->second] = Mtmp;
882 Tout.block[it->second] += Mtmp;
887 Tout.push_back(qTout,Mtmp);
913template<
typename Symmetry,
typename Scalar,
typename MpoMatrixType>
915 const vector<
Biped<Symmetry,Matrix<Scalar,Dynamic,Dynamic> > > &Abra,
917 const vector<
Biped<Symmetry,Matrix<Scalar,Dynamic,Dynamic> > > &Aket,
918 const Tripod<Symmetry,Matrix<Scalar,Dynamic,Dynamic> > &R,
923 std::array<typename Symmetry::qType,3> qCheck;
926 for (
size_t s1=0; s1<qloc.size(); ++s1)
927 for (
size_t s2=0; s2<qloc.size(); ++s2)
928 for (
size_t k=0; k<qOp.size(); ++k)
930 qCheck = {qloc[s2],qOp[k],qloc[s1]};
931 if(!Symmetry::validate(qCheck)) {
continue;}
932 for (
size_t qL=0; qL<L.dim; ++qL)
934 vector<tuple<qarray3<Symmetry::Nq>,size_t,size_t,
size_t> > ix;
935 bool FOUND_MATCH =
LAWA(L.in(qL), L.out(qL), L.mid(qL), qloc[s1], qloc[s2], qOp[k], Abra[s1], Aket[s2], W[s1][s2][k], ix);
936 if (FOUND_MATCH ==
true)
938 for(
size_t n=0; n<ix.size(); n++ )
941 auto qR = R.dict.find(quple);
943 if (qR != R.dict.end())
945 swap(quple[0], quple[1]);
946 size_t qAbra = get<1>(ix[n]);
947 size_t qAket = get<2>(ix[n]);
948 size_t qW = get<3>(ix[n]);
949 if constexpr ( Symmetry::NON_ABELIAN )
951 factor_cgc = Symmetry::coeff_buildL(Aket[s2].in[qAket], qloc[s2], Aket[s2].out[qAket],
952 L.mid(qL) , qOp[k] , quple[2],
953 Abra[s1].in[qAbra], qloc[s1], Abra[s1].out[qAbra]);
959 if (std::abs(factor_cgc) < ::mynumeric_limits<double>::epsilon()) {
continue; }
961 for (
int r=0; r<W[s1][s2][k].block[qW].outerSize(); ++r)
962 for (
typename MpoMatrixType::InnerIterator iW(W[s1][s2][k].block[qW],r); iW; ++iW)
964 size_t a1 = iW.row();
965 size_t a2 = iW.col();
967 if (L.block[qL][a1][0].rows() != 0 and
968 R.block[qR->second][a2][0].rows() != 0)
977 Matrix<Scalar,Dynamic,Dynamic> Mtmp = L.block[qL][a1][0] *
978 Aket[s2].block[qAket] *
979 R.block[qR->second][a2][0];
980 for (
size_t i=0; i<Abra[s1].block[qAbra].cols(); ++i)
982 res += factor_cgc * iW.value() * Abra[s1].block[qAbra].col(i).dot(Mtmp.col(i));
994template<
typename Symmetry,
typename Scalar>
996 const Tripod<Symmetry,Matrix<Scalar,Dynamic,Dynamic> > &L,
997 const Biped <Symmetry,Matrix<Scalar,Dynamic,Dynamic> > &R)
1000 assert(fixed_b.first == Symmetry::qvacuum());
1001 for (
size_t qL=0; qL<L.dim; ++qL)
1004 assert(L.out(qL) == L.in(qL) and
"contract_LR(Tripod,Biped) error!");
1005 if (L.mid(qL) == Symmetry::qvacuum())
1008 auto qR = R.dict.find(quple);
1010 if (qR != R.dict.end())
1012 if (L.block[qL][fixed_b.second][0].size() != 0 and
1013 R.block[qR->second].size() != 0)
1015 res += (L.block[qL][fixed_b.second][0] * R.block[qR->second]).trace() * Symmetry::coeff_dot(L.out(qL));
1024template<
typename Symmetry,
typename Scalar>
1026 const Biped <Symmetry,Matrix<Scalar,Dynamic,Dynamic> > &L,
1027 const Tripod<Symmetry,Matrix<Scalar,Dynamic,Dynamic> > &R)
1030 assert(fixed_a.first == Symmetry::qvacuum());
1031 for (
size_t qR=0; qR<R.dim; ++qR)
1034 assert(R.out(qR) == R.in(qR) and
"contract_LR(Biped,Tripod) error!");
1036 if (R.mid(qR) == Symmetry::qvacuum())
1039 auto qL = L.dict.find(quple);
1041 if (qL != L.dict.end())
1043 if (R.block[qR][fixed_a.second][0].size() != 0 and
1044 L.block[qL->second].size() != 0)
1048 res += (L.block[qL->second] * R.block[qR][fixed_a.second][0]).trace() * Symmetry::coeff_dot(R.out(qR));
1056template<
typename Symmetry,
typename Scalar>
1058 const Tripod<Symmetry,Matrix<Scalar,Dynamic,Dynamic> > &R)
1062 for (
size_t qL=0; qL<L.dim; ++qL)
1065 auto qR = R.dict.find(quple);
1067 if (qR != R.dict.end())
1069 if (L.block[qL].shape()[0] != R.block[qR->second].shape()[0])
1071 cout <<
"L.block[qL].shape()[0]=" << L.block[qL].shape()[0] << endl;
1072 cout <<
"R.block[qR->second].shape()[0]=" << R.block[qR->second].shape()[0] << endl;
1074 assert(L.block[qL].shape()[0] == R.block[qR->second].shape()[0]);
1076 for (
size_t a=0; a<L.block[qL].shape()[0]; ++a)
1078 if (L.block[qL][a][0].size() != 0 and
1079 R.block[qR->second][a][0].size() != 0)
1081 res += (L.block[qL][a][0] * R.block[qR->second][a][0]).trace() * Symmetry::coeff_dot(L.in(qL));
1278template<
typename Symmetry,
typename MatrixType,
typename MpoMatrixType>
1299 auto TensorBaseRight = baseRightTop.
combine(baseRightBot);
1300 auto TensorBaseLeft = baseLeftTop.
combine(baseLeftBot);
1302 std::array<typename Symmetry::qType,3> qCheck;
1304 typename MpoMatrixType::Scalar factor_cgc, factor_merge, factor_check;
1308 for (
size_t s1=0; s1<qloc.size(); ++s1)
1309 for (
size_t s2=0; s2<qloc.size(); ++s2)
1310 for (
size_t s3=0; s3<qloc.size(); ++s3)
1311 for (
size_t k1=0; k1<qOpTop.size(); ++k1)
1312 for (
size_t k2=0; k2<qOpBot.size(); ++k2)
1314 qCheck = {qloc[s3],qOpTop[k1],qloc[s2]};
1315 if(!Symmetry::validate(qCheck)) {
continue;}
1316 qCheck = {qloc[s2],qOpBot[k2],qloc[s1]};
1317 if(!Symmetry::validate(qCheck)) {
continue;}
1319 auto ks = Symmetry::reduceSilent(qOpTop[k1],qOpBot[k2]);
1320 for(
const auto& k : ks)
1322 qCheck = {qloc[s3],k,qloc[s1]};
1323 if(!Symmetry::validate(qCheck)) {
continue;}
1326 factor_check = Symmetry::coeff_MPOprod6(qloc[s1],qOpBot[k2],qloc[s2],
1327 qOpTop[k1],qloc[s3],k);
1328 if (std::abs(factor_check) < ::mynumeric_limits<double>::epsilon()) {
continue; }
1329 for (
size_t qR=0; qR<Rold.
dim; ++qR)
1331 auto qRouts = Symmetry::reduceSilent(Rold.
out(qR),Symmetry::flip(qloc[s1]));
1332 auto qRins = Symmetry::reduceSilent(Rold.
in(qR),Symmetry::flip(qloc[s3]));
1333 auto qrightAuxs = Sym::split<Symmetry>(Rold.
mid(qR),baseRightTop.
qs(),baseRightBot.
qs());
1335 for(
const auto& qRout : qRouts)
1336 for(
const auto& qRin : qRins)
1338 auto q1 = Abra[s1].dict.find({qRout, Rold.
out(qR)});
1339 auto q3 = Aket[s3].dict.find({qRin, Rold.
in(qR)});
1340 if (q1!=Abra[s1].dict.end() and q3!=Aket[s3].dict.end())
1342 auto qRmids = Symmetry::reduceSilent(Rold.
mid(qR),Symmetry::flip(k));
1343 for(
const auto& new_qmid : qRmids)
1346 factor_cgc = Symmetry::coeff_buildR(Aket[s3].in[q3->second], qloc[s3], Aket[s3].out[q3->second],
1347 new_qmid , k , Rold.
mid(qR),
1348 Abra[s1].in[q1->second], qloc[s1], Abra[s1].out[q1->second]);
1350 if (std::abs(factor_cgc) < std::abs(::mynumeric_limits<double>::epsilon())) {
continue; }
1351 for(
const auto& [qrightAux,qrightAuxP] : qrightAuxs)
1353 Eigen::Index left2=TensorBaseRight.leftAmount(Rold.
mid(qR),{qrightAux, qrightAuxP});
1354 auto qleftAuxs = Symmetry::reduceSilent(qrightAux,Symmetry::flip(qOpTop[k1]));
1355 for(
const auto& qleftAux : qleftAuxs)
1357 auto qWtop = Wtop[s2][s3][k1].dict.find({qleftAux,qrightAux});
1358 if(qWtop != Wtop[s2][s3][k1].dict.end())
1361 auto qleftAuxPs = Symmetry::reduceSilent(qrightAuxP,Symmetry::flip(qOpBot[k2]));
1362 for(
const auto& qleftAuxP : qleftAuxPs)
1364 auto qWbot = Wbot[s1][s2][k2].dict.find({qleftAuxP,qrightAuxP});
1365 if(qWbot != Wbot[s1][s2][k2].dict.end())
1368 factor_merge = Symmetry::coeff_MPOprod9(qleftAux,qleftAuxP,new_qmid,
1369 qOpTop[k1],qOpBot[k2],k,
1370 qrightAux,qrightAuxP,Rold.
mid(qR));
1371 if (std::abs(factor_merge) < std::abs(::mynumeric_limits<double>::epsilon())) {
continue; }
1372 Eigen::Index left1=TensorBaseLeft.leftAmount(new_qmid,{qleftAux, qleftAuxP});
1373 for (
int ktop=0; ktop<Wtop[s2][s3][k1].block[qWtop->second].outerSize(); ++ktop)
1374 for (
typename MpoMatrixType::InnerIterator iWtop(Wtop[s2][s3][k1].block[qWtop->second],ktop); iWtop; ++iWtop)
1375 for (
int kbot=0; kbot<Wbot[s1][s2][k2].block[qWbot->second].outerSize(); ++kbot)
1376 for (
typename MpoMatrixType::InnerIterator iWbot(Wbot[s1][s2][k2].block[qWbot->second],kbot); iWbot; ++iWbot)
1378 size_t br = iWbot.row();
1379 size_t bc = iWbot.col();
1380 size_t tr = iWtop.row();
1381 size_t tc = iWtop.col();
1382 typename MpoMatrixType::Scalar Wfactor = iWbot.value() * iWtop.value();
1387 size_t a1 = left1+tr*Wbot[s1][s2][k2].block[qWbot->second].rows()+br;
1388 size_t a2 = left2+tc*Wbot[s1][s2][k2].block[qWbot->second].cols()+bc;
1390 if (Rold.
block[qR][a2][0].rows() != 0)
1394 Aket[s3].block[q3->second],
1395 Rold.
block[qR][a2][0],
1396 Abra[s1].block[q1->second].adjoint(),
1398 auto it = Rnew.
dict.find(quple);
1400 if (it != Rnew.
dict.end())
1402 if (Rnew.
block[it->second][a1][0].rows() != Mtmp.rows() or
1403 Rnew.
block[it->second][a1][0].cols() != Mtmp.cols())
1405 Rnew.
block[it->second][a1][0] = Mtmp;
1409 Rnew.
block[it->second][a1][0] += Mtmp;
1414 boost::multi_array<MatrixType,LEGLIMIT> Mtmpvec(boost::extents[TensorBaseLeft.inner_dim(new_qmid)][1]);
1415 Mtmpvec[a1][0] = Mtmp;
1438template<
typename Symmetry,
typename MatrixType,
typename MpoMatrixType>
1449 std::array<typename Symmetry::qType,3> qCheck;
1453 for (
size_t s1=0; s1<qloc.size(); ++s1)
1454 for (
size_t s2=0; s2<qloc.size(); ++s2)
1455 for (
size_t s3=0; s3<qloc.size(); ++s3)
1456 for (
size_t k1=0; k1<qOpBot.size(); ++k1)
1457 for (
size_t k2=0; k2<qOpTop.size(); ++k2)
1459 qCheck = {qloc[s2],qOpBot[k1],qloc[s1]};
1460 if(!Symmetry::validate(qCheck)) {
continue;}
1461 qCheck = {qloc[s3],qOpTop[k2],qloc[s2]};
1462 if(!Symmetry::validate(qCheck)) {
continue;}
1463 for (
size_t qL=0; qL<Lold.
dim; ++qL)
1465 tuple<qarray4<Symmetry::Nq>,size_t,size_t, size_t,
size_t> ix;
1466 bool FOUND_MATCH =
AWWA(Lold.
in(qL), Lold.
out(qL), Lold.
bot(qL), Lold.
top(qL),
1467 qloc[s1], qloc[s2], qloc[s3], qOpBot[k1], qOpTop[k2], Abra[s1], Aket[s3], Wbot[s1][s2][k1], Wtop[s2][s3][k2], ix);
1468 auto quple = get<0>(ix);
1469 swap(quple[0],quple[1]);
1470 size_t qAbra = get<1>(ix);
1471 size_t qAket = get<2>(ix);
1472 size_t qWbot = get<3>(ix);
1473 size_t qWtop = get<4>(ix);
1475 if (FOUND_MATCH ==
true)
1477 for (
int kbot=0; kbot<Wbot[s1][s2][k1].block[qWbot].outerSize(); ++kbot)
1478 for (
typename MpoMatrixType::InnerIterator iWbot(Wbot[s1][s2][k1].block[qWbot],kbot); iWbot; ++iWbot)
1479 for (
int ktop=0; ktop<Wtop[s2][s3][k2].block[qWtop].outerSize(); ++ktop)
1480 for (
typename MpoMatrixType::InnerIterator iWtop(Wtop[s2][s3][k2].block[qWtop],ktop); iWtop; ++iWtop)
1482 size_t br = iWbot.row();
1483 size_t bc = iWbot.col();
1484 size_t tr = iWtop.row();
1485 size_t tc = iWtop.col();
1486 typename MpoMatrixType::Scalar Wfactor = iWbot.value() * iWtop.value();
1488 if (Lold.
block[qL][br][tr].rows() != 0)
1492 Abra[s1].block[qAbra].adjoint(),
1493 Lold.
block[qL][br][tr],
1494 Aket[s3].block[qAket],
1497 if (Mtmp.norm() != 0.)
1499 auto it = Lnew.
dict.find(quple);
1500 if (it != Lnew.
dict.end())
1502 if (Lnew.
block[it->second][bc][tc].rows() != Mtmp.rows() or
1503 Lnew.
block[it->second][bc][tc].cols() != Mtmp.cols())
1505 Lnew.
block[it->second][bc][tc] = Mtmp;
1509 Lnew.
block[it->second][bc][tc] += Mtmp;
1514 size_t bcols = Wbot[s1][s2][k1].block[qWbot].cols();
1515 size_t tcols = Wtop[s2][s3][k2].block[qWtop].cols();
1516 boost::multi_array<MatrixType,LEGLIMIT> Mtmparray(boost::extents[bcols][tcols]);
1517 Mtmparray[bc][tc] = Mtmp;
1529template<
typename Symmetry,
typename MatrixType,
typename MpoMatrixType>
1537 Cnext.resize(qloc.size());
1538 std::array<typename Symmetry::qType,3> qCheck;
1540 for (
size_t s2=0; s2<qloc.size(); ++s2)
1543 auto qA = Aket[s2].dict.find(cmpA);
1545 if (qA != Aket[s2].dict.end())
1547 for (
size_t s1=0; s1<qloc.size(); ++s1)
1548 for (
size_t k=0; k<qOp.size(); ++k)
1550 qCheck = {qloc[s2],qOp[k],qloc[s1]};
1551 if(!Symmetry::validate(qCheck)) {
continue;}
1552 for (
int r=0; r<W[s1][s2][k].outerSize(); ++r)
1553 for (
typename MpoMatrixType::InnerIterator iW(W[s1][s2][k][0],r); iW; ++iW)
1555 MatrixType Mtmp = iW.value() * Aket[s2].block[qA->second];
1557 qarray3<Symmetry::Nq> cmpC = {Symmetry::qvacuum(), Aket[s2].out[qA->second], Symmetry::qvacuum()+qloc[s1]-qloc[s2]};
1558 auto qCnext = Cnext[s1].dict.find(cmpC);
1559 if (qCnext != Cnext[s1].dict.end())
1561 if (Cnext[s1].block[qCnext->second][iW.col()][0].rows() != Mtmp.rows() or
1562 Cnext[s1].block[qCnext->second][iW.col()][0].cols() != Mtmp.cols())
1564 Cnext[s1].block[qCnext->second][iW.col()][0] = Mtmp;
1568 Cnext[s1].block[qCnext->second][iW.col()][0] += Mtmp;
1573 boost::multi_array<MatrixType,LEGLIMIT> Mtmpvec(boost::extents[W[s1][s2][k][0].cols()][1]);
1574 Mtmpvec[iW.col()][0] = Mtmp;
1575 Cnext[s1].push_back({Symmetry::qvacuum(), Aket[s2].out[qA->second], Symmetry::qvacuum()+qloc[s1]-qloc[s2]}, Mtmpvec);
1585template<
typename Symmetry,
typename MatrixType,
typename MpoMatrixType>
1595 Cnext.resize(qloc.size());
1596 std::array<typename Symmetry::qType,3> qCheck;
1598 for (
size_t s=0; s<qloc.size(); ++s)
1599 for (
size_t qC=0; qC<C[s].dim; ++qC)
1602 auto qU = Abra[s].dict.find(cmpU);
1604 if (qU != Abra[s].dict.end())
1606 for (
size_t s1=0; s1<qloc.size(); ++s1)
1607 for (
size_t s2=0; s2<qloc.size(); ++s2)
1608 for (
size_t k=0; k<qOp.size(); ++k)
1610 qCheck = {qloc[s2],qOp[k],qloc[s1]};
1611 if(!Symmetry::validate(qCheck)) {
continue;}
1614 auto qA = Aket[s2].dict.find(cmpA);
1616 if (qA != Aket[s2].dict.end())
1618 for (
int r=0; r<W[s1][s2][k][0].outerSize(); ++r)
1619 for (
typename MpoMatrixType::InnerIterator iW(W[s1][s2][k][0],r); iW; ++iW)
1621 if (C[s].block[qC][iW.row()][0].rows() != 0)
1628 Abra[s].block[qU->second].adjoint(),
1629 C[s].block[qC][iW.row()][0],
1630 Aket[s2].block[qA->second],
1633 qarray3<Symmetry::Nq> cmpC = {Abra[s].out[qU->second], Aket[s2].out[qA->second], C[s].mid(qC)+qloc[s1]-qloc[s2]};
1634 auto qCnext = Cnext[s1].dict.find(cmpC);
1635 if (qCnext != Cnext[s1].dict.end())
1637 if (Cnext[s1].block[qCnext->second][iW.col()][0].rows() != Mtmp.rows() or
1638 Cnext[s1].block[qCnext->second][iW.col()][0].cols() != Mtmp.cols())
1640 Cnext[s1].block[qCnext->second][iW.col()][0] = Mtmp;
1644 Cnext[s1].block[qCnext->second][iW.col()][0] += Mtmp;
1649 boost::multi_array<MatrixType,LEGLIMIT> Mtmpvec(boost::extents[W[s1][s2][0][0].cols()][1]);
1650 Mtmpvec[iW.col()][0] = Mtmp;
1651 Cnext[s1].push_back({Abra[s].out[qU->second], Aket[s2].out[qA->second], C[s].mid(qC)+qloc[s1]-qloc[s2]}, Mtmpvec);
1721template<
typename Symmetry,
typename Scalar,
typename MpoMatrixType>
1730 vector<
Biped<Symmetry,Matrix<Scalar,Dynamic,Dynamic> > > &Aout,
1731 bool FORCE_QTOT=
false,
1734 for (
size_t s=0; s<qloc.size(); ++s)
1741 auto tensorBasis_l = qauxAl.
combine(qauxWl);
1742 auto tensorBasis_r = qauxAr.
combine(qauxWr);
1744 for (
size_t s1=0; s1<qloc.size(); ++s1)
1745 for (
size_t s2=0; s2<qloc.size(); ++s2)
1746 for (
size_t k=0; k<qOp.size(); ++k)
1749 if (!Symmetry::validate(qCheck_)) {
continue; }
1752 for (
size_t q=0; q<Ain[s2].size(); q++)
1754 for (
auto it=qauxWl.
cbegin(); it != qauxWl.
cend(); it++)
1756 auto [qWl, qWl_dim, qWl_plain] = *it;
1757 auto qWrs = Symmetry::reduceSilent(qWl,qOp[k]);
1759 for (
const auto &qWr : qWrs)
1761 if (qauxWr.
find(qWr) ==
false) {
continue;}
1763 auto qmerge_ls = Symmetry::reduceSilent(Ain[s2].in[q] ,qWl);
1764 auto qmerge_rs = Symmetry::reduceSilent(Ain[s2].out[q],qWr);
1766 for (
const auto qmerge_l : qmerge_ls)
1767 for (
const auto qmerge_r : qmerge_rs)
1771 if (!Symmetry::validate(qCheck)) {
continue; }
1772 if (tensorBasis_l.find(qmerge_l) ==
false) {
continue;}
1773 if (tensorBasis_r.find(qmerge_r) ==
false) {
continue;}
1775 if constexpr (Symmetry::NON_ABELIAN)
1777 factor_cgc = Symmetry::coeff_AW(Ain[s2].in[q], qloc[s2], Ain[s2].out[q],
1779 qmerge_l , qloc[s1], qmerge_r);
1781 else { factor_cgc = 1.; }
1783 if (abs(factor_cgc) < abs(mynumeric_limits<double>::epsilon())) {
continue; }
1785 Matrix<Scalar,Dynamic,Dynamic> Mtmp(tensorBasis_l.inner_dim(qmerge_l), tensorBasis_r.inner_dim(qmerge_r)); Mtmp.setZero();
1786 int left_l = tensorBasis_l.leftAmount(qmerge_l, { Ain[s2].in[q] , qWl } );
1787 int left_r = tensorBasis_r.leftAmount(qmerge_r, { Ain[s2].out[q], qWr } );
1789 auto dict_entry = W[s1][s2][k].dict.find({qWl,qWr});
1790 if(dict_entry == W[s1][s2][k].dict.end())
continue;
1791 size_t qW = dict_entry->second;
1793 for (
int r=0; r<W[s1][s2][k].block[qW].outerSize(); ++r)
1794 for (
typename MpoMatrixType::InnerIterator iW(W[s1][s2][k].block[qW],r); iW; ++iW)
1796 size_t wr = iW.row() * Ain[s2].block[q].rows();
1797 size_t wc = iW.col() * Ain[s2].block[q].cols();
1798 Mtmp.block(wr+left_l,wc+left_r,Ain[s2].block[q].rows(),Ain[s2].block[q].cols()) += Ain[s2].block[q] * iW.value() * factor_cgc;
1802 auto it = Aout[s1].dict.find(cmp);
1806 if (it == Aout[s1].dict.end())
1808 Aout[s1].push_back(cmp,Mtmp);
1812 Aout[s1].block[it->second] += Mtmp;
1817 if (it == Aout[s1].dict.end() and cmp[1] == Qtot)
1819 Aout[s1].push_back(cmp,Mtmp);
1821 else if (it != Aout[s1].dict.end() and cmp[1] == Qtot)
1823 Aout[s1].block[it->second] += Mtmp;
1832template<
typename Symmetry,
typename Scalar>
1835 vector<Biped<Symmetry,Matrix<Scalar,Dynamic,Dynamic> > > Aout(
A.size());
1839 for (
size_t s=0; s<qloc.size(); s++)
1840 for (
const auto & [qin,num,plain] : in)
1842 auto qouts = Symmetry::reduceSilent(qin,qloc[s]);
1843 for (
const auto & qout:qouts)
1845 if (!out.
find(qout)) {
continue;}
1847 auto it_A =
A[s].dict.find(cmp);
1848 if (it_A !=
A[s].dict.end())
1850 Aout[s].push_back(qin,qout,
A[s].block[it_A->second]);
1854 Matrix<Scalar,Dynamic,Dynamic> Mtmp(in.
inner_dim(qin), out.
inner_dim(qout)); Mtmp.setZero();
1855 Aout[s].push_back(qin,qout,Mtmp);
1862template<
typename Symmetry,
typename Scalar>
1865 const auto copy =
A;
1869template<
typename Symmetry,
typename Scalar>
1872 const vector<
Biped<Symmetry,Matrix<Scalar,Dynamic,Dynamic> > > &A2,
1874 vector<
Biped<Symmetry,Matrix<Scalar,Dynamic,Dynamic> > > &Apair,
1879 auto locBasis = locBasis1.
combine(locBasis2);
1881 Apair.resize(locBasis.size());
1882 for (
size_t s1=0; s1<qloc1.size(); s1++)
1883 for (
size_t s2=0; s2<qloc2.size(); s2++)
1885 auto q_s1s2s = Symmetry::reduceSilent(qloc1[s1],qloc2[s2]);
1886 for (
const auto &q_s1s2: q_s1s2s)
1889 size_t s1s2 = locBasis.outer_num(q_s1s2) + locBasis.leftOffset(q_s1s2,{qloc1[s1],qloc2[s2]},{locBasis1.
inner_num(s1),locBasis2.
inner_num(s2)});
1891 for (
size_t q1=0; q1<A1[s1].size(); q1++)
1893 typename Symmetry::qType qm = A1[s1].out[q1];
1894 auto q2s = Symmetry::reduceSilent(qm,qloc2[s2]);
1895 for (
const auto &q2 : q2s)
1897 auto it_q2 = A2[s2].dict.find({qm,q2});
1898 if ( it_q2 == A2[s2].dict.end()) {
continue;}
1899 Eigen::Matrix<Scalar,-1,-1> Mtmp(A1[s1].block[q1].rows(),A2[s2].block[it_q2->second].cols());
1901 Scalar factor_cgc = Symmetry::coeff_twoSiteGate(A1[s1].in[q1], qloc1[s1], qm,
1902 qloc2[s2] , q2 , q_s1s2);
1903 if (abs(factor_cgc) < ::mynumeric_limits<double>::epsilon()) {
continue;}
1911 Mtmp = factor_cgc * A1[s1].block[q1] * A2[s2].block[it_q2->second];
1914 auto it_pair = Apair[s1s2].dict.find({A1[s1].in[q1],q2});
1915 if (it_pair == Apair[s1s2].dict.end())
1917 Apair[s1s2].push_back(A1[s1].in[q1],q2,Mtmp);
1921 Apair[s1s2].block[it_pair->second] += Mtmp;
1929template<
typename Symmetry,
typename Scalar>
1932 const vector<
Biped<Symmetry,Matrix<Scalar,Dynamic,Dynamic> > > &A2,
1936 vector<
Biped<Symmetry,Matrix<Scalar,Dynamic,Dynamic> > > &Apair,
1939 auto tensor_basis = Symmetry::tensorProd(qloc1,qloc2);
1940 Apair.resize(tensor_basis.size());
1942 vector<qarray<Symmetry::Nq> > qsplit =
calc_qsplit (A1, qloc1, A2, qloc2, Qtop, Qbot);
1944 vector<qarray<Symmetry::Nq> > A1in;
1945 vector<qarray<Symmetry::Nq> > A2out;
1948 for (
size_t s1=0; s1<qloc1.size(); ++s1)
1949 for (
size_t q=0; q<A1[s1].dim; ++q)
1951 A1in.push_back(A1[s1].in[q]);
1954 for (
size_t s2=0; s2<qloc2.size(); ++s2)
1955 for (
size_t q=0; q<A2[s2].dim; ++q)
1957 A2out.push_back(A2[s2].out[q]);
1960 for (
size_t s1=0; s1<qloc1.size(); ++s1)
1961 for (
size_t m=0; m<qsplit.size(); ++m)
1963 auto qins = Symmetry::reduceSilent(qsplit[m], Symmetry::flip(qloc1[s1]));
1965 for (
const auto &qin:qins)
1967 for (
size_t s2=0; s2<qloc2.size(); ++s2)
1969 auto qmerges = Symmetry::reduceSilent(qloc1[s1], qloc2[s2]);
1971 for (
const auto &qmerge:qmerges)
1973 auto qtensor = make_tuple(qloc1[s1], s1, qloc2[s2], s2, qmerge);
1974 auto s1s2 = distance(tensor_basis.begin(), find(tensor_basis.begin(), tensor_basis.end(), qtensor));
1976 auto qouts = Symmetry::reduceSilent(qsplit[m], qloc2[s2]);
1977 for (
const auto &qout:qouts)
1979 auto qA1 = find(A1in.begin(), A1in.end(), qin);
1980 auto qA2 = find(A2out.begin(), A2out.end(), qout);
1981 if (qA1 != A1in.end() and qA2 != A2out.end())
1983 Apair[s1s2].try_create_block({qin,qout});
1991 #ifdef DMRG_CONTRACTAA_PARALLELIZE
1992 #pragma omp parallel for collapse(2) schedule(dynamic)
1994 for (
size_t s1=0; s1<qloc1.size(); ++s1)
1995 for (
size_t s2=0; s2<qloc2.size(); ++s2)
1997 auto qmerges = Symmetry::reduceSilent(qloc1[s1], qloc2[s2]);
1999 for (
const auto &qmerge:qmerges)
2001 auto qtensor = make_tuple(qloc1[s1], s1, qloc2[s2], s2, qmerge);
2002 auto s1s2 = distance(tensor_basis.begin(), find(tensor_basis.begin(), tensor_basis.end(), qtensor));
2004 for (
size_t q1=0; q1<A1[s1].dim; ++q1)
2006 auto qouts = Symmetry::reduceSilent(A1[s1].out[q1], qloc2[s2]);
2008 for (
const auto &qout:qouts)
2011 auto q2 = A2[s2].dict.find(quple);
2013 if (q2 != A2[s2].dict.end())
2015 Scalar factor_cgc = Symmetry::coeff_Apair(A1[s1].in[q1], qloc1[s1], A1[s1].out[q1],
2016 qloc2[s2], A2[s2].out[q2->second], qmerge);
2017 if (abs(factor_cgc) > abs(mynumeric_limits<double>::epsilon()))
2019 Matrix<Scalar,Dynamic,Dynamic> Mtmp;
2022 Mtmp = factor_cgc * A1[s1].block[q1] * A2[s2].block[q2->second];
2025 if (Mtmp.size() != 0)
2027 #pragma omp critical
2031 auto qApair = Apair[s1s2].dict.find(qupleApair);
2033 if (qApair != Apair[s1s2].dict.end() and
2034 Apair[s1s2].block[qApair->second].size() == Mtmp.size())
2036 Apair[s1s2].block[qApair->second] += Mtmp;
2038 else if (qApair != Apair[s1s2].dict.end() and
2039 Apair[s1s2].block[qApair->second].size() == 0)
2041 Apair[s1s2].block[qApair->second] = Mtmp;
2045 Apair[s1s2].push_back(qupleApair, Mtmp);
2058template<
typename Symmetry,
typename Scalar>
2061 const vector<
Biped<Symmetry,Matrix<Scalar,Dynamic,Dynamic> > > &A2,
2063 const vector<
Biped<Symmetry,Matrix<Scalar,Dynamic,Dynamic> > > &A3,
2065 const vector<
Biped<Symmetry,Matrix<Scalar,Dynamic,Dynamic> > > &A4,
2067 boost::multi_array<
Biped<Symmetry,Matrix<Scalar,Dynamic,Dynamic> >,4> &Aquartett)
2069 Aquartett.resize(boost::extents[qloc1.size()][qloc2.size()][qloc3.size()][qloc4.size()]);
2071 for (
size_t s1=0; s1<qloc1.size(); ++s1)
2072 for (
size_t s2=0; s2<qloc2.size(); ++s2)
2073 for (
size_t s3=0; s3<qloc3.size(); ++s3)
2074 for (
size_t s4=0; s4<qloc4.size(); ++s4)
2075 for (
size_t q1=0; q1<A1[s1].dim; ++q1)
2078 auto q2 = A2[s2].dict.find(quple2);
2080 if (q2 != A2[s2].dict.end())
2083 auto q3 = A3[s3].dict.find(quple3);
2085 if (q3 != A3[s3].dict.end())
2088 auto q4 = A4[s4].dict.find(quple4);
2090 if (q4 != A4[s4].dict.end())
2092 Matrix<Scalar,Dynamic,Dynamic> Mtmp = A1[s1].block[q1] *
2093 A2[s2].block[q2->second] *
2094 A3[s3].block[q3->second] *
2095 A4[s4].block[q4->second];
2098 auto qAquartett = Aquartett[s1][s2][s3][s4].dict.find(qupleAquartett);
2100 if (qAquartett != Aquartett[s1][s2][s3][s4].dict.end())
2102 Aquartett[s1][s2][s3][s4].block[qAquartett->second] += Mtmp;
2106 Aquartett[s1][s2][s3][s4].push_back(qupleAquartett, Mtmp);
2114template<
typename Symmetry,
typename Scalar>
2121 double truncDump, Sdump;
2122 split_AA(DIR, Apair, qloc_l, Al, qloc_r, Ar, qtop, qbot,
2123 Cdump,
false, truncDump, Sdump, eps_svd,min_Nsv,max_Nsv);
2126template<
typename Symmetry,
typename Scalar>
2131 Biped<Symmetry,Matrix<Scalar,Dynamic,Dynamic> > &C,
bool SEPARATE_SV,
double &truncWeight,
double &S,
double eps_svd,
size_t min_Nsv,
size_t max_Nsv)
2133 vector<qarray<Symmetry::Nq> > midset =
calc_qsplit(Al, qloc_l, Ar, qloc_r, qtop, qbot);
2135 for (
size_t s=0; s<qloc_l.size(); ++s)
2139 for (
size_t s=0; s<qloc_r.size(); ++s)
2144 ArrayXd truncWeightSub(midset.size()); truncWeightSub.setZero();
2145 ArrayXd entropySub(midset.size()); entropySub.setZero();
2147 auto tensor_basis = Symmetry::tensorProd(qloc_l, qloc_r);
2149 #ifdef DMRG_SPLITAA_PARALLELIZE
2150 #pragma omp parallel for schedule(dynamic)
2152 for (
size_t qmid=0; qmid<midset.size(); ++qmid)
2154 map<pair<size_t,qarray<Symmetry::Nq> >,vector<pair<size_t,qarray<Symmetry::Nq> > > > s13map;
2159 for (
size_t s1=0; s1<qloc_l.size(); ++s1)
2160 for (
size_t s3=0; s3<qloc_r.size(); ++s3)
2162 auto qmerges = Symmetry::reduceSilent(qloc_l[s1], qloc_r[s3]);
2164 for (
const auto &qmerge:qmerges)
2166 auto qtensor = make_tuple(qloc_l[s1], s1, qloc_r[s3], s3, qmerge);
2167 auto s1s3 = distance(tensor_basis.begin(), find(tensor_basis.begin(), tensor_basis.end(), qtensor));
2169 for (
size_t q13=0; q13<Apair[s1s3].dim; ++q13)
2171 auto qlmids = Symmetry::reduceSilent(Apair[s1s3].in[q13], qloc_l[s1]);
2172 auto qrmids = Symmetry::reduceSilent(Apair[s1s3].out[q13], Symmetry::flip(qloc_r[s3]));
2174 for (
const auto &qlmid:qlmids)
2175 for (
const auto &qrmid:qrmids)
2177 if (qlmid == midset[qmid] and qrmid == midset[qmid])
2179 s13map[make_pair(s1,Apair[s1s3].in[q13])].push_back(make_pair(s3,Apair[s1s3].out[q13]));
2181 Scalar factor_cgc = Symmetry::coeff_Apair(Apair[s1s3].in[q13], qloc_l[s1], midset[qmid],
2182 qloc_r[s3], Apair[s1s3].out[q13], qmerge);
2185 factor_cgc *= Symmetry::coeff_leftSweep(Apair[s1s3].out[q13],midset[qmid]);
2188 cgcmap[make_tuple(s1,Apair[s1s3].in[q13],s3,Apair[s1s3].out[q13])].push_back(factor_cgc);
2189 q13map[make_tuple(s1,Apair[s1s3].in[q13],s3,Apair[s1s3].out[q13])].push_back(q13);
2190 s1s3map[make_tuple(s1,Apair[s1s3].in[q13],s3,Apair[s1s3].out[q13])].push_back(s1s3);
2197 if (s13map.size() != 0)
2199 map<pair<size_t,qarray<Symmetry::Nq> >,Matrix<Scalar,Dynamic,Dynamic> > Aclumpvec;
2202 vector<size_t> get_s3;
2203 vector<size_t> get_Ncols;
2204 vector<qarray<Symmetry::Nq> > get_qr;
2205 bool COLS_ARE_KNOWN =
false;
2207 for (
size_t s1=0; s1<qloc_l.size(); ++s1)
2209 auto qls = Symmetry::reduceSilent(midset[qmid], Symmetry::flip(qloc_l[s1]));
2211 for (
const auto &ql:qls)
2213 for (
size_t s3=0; s3<qloc_r.size(); ++s3)
2215 auto qrs = Symmetry::reduceSilent(midset[qmid], qloc_r[s3]);
2217 for (
const auto &qr:qrs)
2219 auto s3block = find(s13map[make_pair(s1,ql)].begin(), s13map[make_pair(s1,ql)].end(), make_pair(s3,qr));
2221 if (s3block != s13map[make_pair(s1,ql)].end())
2223 Matrix<Scalar,Dynamic,Dynamic> Mtmp;
2224 for (
size_t i=0; i<q13map[make_tuple(s1,ql,s3,qr)].size(); ++i)
2226 size_t q13 = q13map[make_tuple(s1,ql,s3,qr)][i];
2227 size_t s1s3 = s1s3map[make_tuple(s1,ql,s3,qr)][i];
2229 if (Mtmp.size() == 0)
2231 Mtmp = cgcmap[make_tuple(s1,ql,s3,qr)][i] * Apair[s1s3].block[q13];
2233 else if (Mtmp.size() > 0 and Apair[s1s3].block[q13].size() > 0)
2235 Mtmp += cgcmap[make_tuple(s1,ql,s3,qr)][i] * Apair[s1s3].block[q13];
2238 if (Mtmp.size() == 0) {
continue;}
2240 addRight(Mtmp, Aclumpvec[make_pair(s1,ql)]);
2242 if (COLS_ARE_KNOWN ==
false)
2244 get_s3.push_back(s3);
2245 get_Ncols.push_back(Mtmp.cols());
2246 get_qr.push_back(qr);
2251 if (get_s3.size() != 0) {COLS_ARE_KNOWN =
true;}
2255 vector<size_t> get_s1;
2256 vector<size_t> get_Nrows;
2257 vector<qarray<Symmetry::Nq> > get_ql;
2258 Matrix<Scalar,Dynamic,Dynamic> Aclump;
2259 for (
size_t s1=0; s1<qloc_l.size(); ++s1)
2261 auto qls = Symmetry::reduceSilent(midset[qmid], Symmetry::flip(qloc_l[s1]));
2263 for (
const auto &ql:qls)
2265 size_t Aclump_rows_old = Aclump.rows();
2269 if (Aclumpvec[make_pair(s1,ql)].cols() < Aclump.cols())
2271 size_t dcols = Aclump.cols() - Aclumpvec[make_pair(s1,ql)].cols();
2272 Aclumpvec[make_pair(s1,ql)].conservativeResize(Aclumpvec[make_pair(s1,ql)].rows(), Aclump.cols());
2273 Aclumpvec[make_pair(s1,ql)].rightCols(dcols).setZero();
2275 else if (Aclumpvec[make_pair(s1,ql)].cols() > Aclump.cols())
2277 size_t dcols = Aclumpvec[make_pair(s1,ql)].cols() - Aclump.cols();
2278 Aclump.conservativeResize(Aclump.rows(), Aclump.cols()+dcols);
2279 Aclump.rightCols(dcols).setZero();
2282 addBottom(Aclumpvec[make_pair(s1,ql)], Aclump);
2284 if (Aclump.rows() > Aclump_rows_old)
2286 get_s1.push_back(s1);
2287 get_Nrows.push_back(Aclump.rows()-Aclump_rows_old);
2288 get_ql.push_back(ql);
2292 if (Aclump.size() == 0)
2305 #ifdef DONT_USE_BDCSVD
2306 JacobiSVD<Matrix<Scalar,Dynamic,Dynamic> > Jack;
2308 BDCSVD<Matrix<Scalar,Dynamic,Dynamic> > Jack;
2310 Jack.compute(Aclump,ComputeThinU|ComputeThinV);
2311 VectorXd SV = Jack.singularValues();
2314 size_t Nret = (SV.array().abs() > eps_svd).count();
2315 Nret = max(Nret, min_Nsv);
2316 Nret = min(Nret, max_Nsv);
2317 truncWeightSub(qmid) = Symmetry::degeneracy(midset[qmid]) * SV.tail(SV.rows()-Nret).cwiseAbs2().sum();
2318 size_t Nnz = (Jack.singularValues().array() > 0.).count();
2319 entropySub(qmid) = -Symmetry::degeneracy(midset[qmid]) *
2320 (SV.head(Nnz).array().square() * SV.head(Nnz).array().square().log()).
sum();
2322 Matrix<Scalar,Dynamic,Dynamic> Aleft, Aright, Cmatrix;
2325 Aleft = Jack.matrixU().leftCols(Nret);
2328 Aright = Jack.matrixV().adjoint().topRows(Nret);
2329 Cmatrix = Jack.singularValues().head(Nret).asDiagonal();
2333 Aright = Jack.singularValues().head(Nret).asDiagonal() * Jack.matrixV().adjoint().topRows(Nret);
2339 Aright = Jack.matrixV().adjoint().topRows(Nret);
2342 Aleft = Jack.matrixU().leftCols(Nret);
2343 Cmatrix = Jack.singularValues().head(Nret).asDiagonal();
2347 Aleft = Jack.matrixU().leftCols(Nret) * Jack.singularValues().head(Nret).asDiagonal();
2353 #pragma omp critical
2356 for (
size_t i=0; i<get_s1.size(); ++i)
2358 size_t s1 = get_s1[i];
2359 size_t Nrows = get_Nrows[i];
2362 auto q = Al[s1].dict.find(quple);
2363 if (q != Al[s1].dict.end())
2365 Al[s1].block[q->second] += Aleft.block(istitch,0, Nrows,Nret);
2369 Al[s1].push_back(get_ql[i], midset[qmid], Aleft.block(istitch,0, Nrows,Nret));
2376 for (
size_t i=0; i<get_s3.size(); ++i)
2378 size_t s3 = get_s3[i];
2379 size_t Ncols = get_Ncols[i];
2382 auto q = Ar[s3].dict.find(quple);
2385 if (q != Ar[s3].dict.end())
2387 Ar[s3].block[q->second] += factor_cgc3 * Aright.block(0,jstitch, Nret,Ncols);
2391 Ar[s3].push_back(midset[qmid], get_qr[i], factor_cgc3 * Aright.block(0,jstitch, Nret,Ncols));
2399 auto q = C.dict.find(quple);
2400 if (q != C.dict.end())
2402 C.block[q->second] += Cmatrix;
2406 C.push_back(midset[qmid], midset[qmid], Cmatrix);
2414 for (
size_t s=0; s<qloc_l.size(); ++s)
2416 Al[s] = Al[s].cleaned();
2418 for (
size_t s=0; s<qloc_r.size(); ++s)
2420 Ar[s] = Ar[s].cleaned();
2423 truncWeight = truncWeightSub.sum();
2424 S = entropySub.sum();
2443template<
typename Symmetry,
typename Scalar>
2450 double truncDump, Sdump;
2451 map<qarray<Symmetry::Nq>,ArrayXd> SVspec_dumb;
2452 split_AA2(DIR, locBasis, Apair, qloc_l, Al, qloc_r, Ar, qtop, qbot,
2453 Cdump,
false, truncDump, Sdump, SVspec_dumb, eps_svd,min_Nsv,max_Nsv);
2460template<
typename Symmetry,
typename Scalar>
2465 Biped<Symmetry,Matrix<Scalar,Dynamic,Dynamic> > &C,
bool SEPARATE_SV,
double &truncWeight,
double &S, map<
qarray<Symmetry::Nq>,ArrayXd> &SVspec,
2466 double eps_truncWeight,
size_t min_Nsv,
size_t max_Nsv)
2483 for (
size_t s=0; s<qloc_l.size(); ++s)
2487 for (
size_t s=0; s<qloc_r.size(); ++s)
2492 Biped<Symmetry,Eigen::Matrix<Scalar,-1,-1> > Aclump;
2493 for (
size_t sl=0; sl<qloc_l.size(); sl++)
2494 for (
size_t sr=0; sr<qloc_r.size(); sr++)
2496 auto q_slsrs = Symmetry::reduceSilent(qloc_l[sl],qloc_r[sr]);
2497 for (
const auto &q_slsr:q_slsrs)
2502 assert(locBasis.
find(s) == q_slsr);
2504 for (
size_t q=0; q<Apair[s].size(); q++)
2506 auto Qls = Symmetry::reduceSilent(Apair[s].in[q],qloc_l[sl]);
2507 auto Qrs = Symmetry::reduceSilent(Apair[s].out[q],Symmetry::flip(qloc_r[sr]));
2508 for (
const auto &Ql:Qls)
2509 for (
const auto &Qr:Qrs)
2511 if (Ql != Qr) {
continue;}
2514 Scalar factor_cgc = Symmetry::coeff_splitAA(Apair[s].in[q], Apair[s].out[q], q_slsr,
2515 qloc_r[sr] , qloc_l[sl] , Ql);
2516 if (abs(factor_cgc) < ::mynumeric_limits<double>::epsilon()) {
continue;}
2523 Index left1 = leftTot.
leftOffset(Ql, {Apair[s].in[q], qloc_l[sl]}, {0, locBasis_l.
inner_num(sl)});
2525 array<qarray<Symmetry::Nq>,2> source = {Apair[s].out[q], Symmetry::flip(qloc_r[sr])};
2529 Mtmp.block(left1, left2, Apair[s].block[q].rows(), Apair[s].block[q].cols()) += factor_cgc*Apair[s].block[q];
2530 auto it_Aclump = Aclump.dict.find({Ql,Qr});
2531 if (it_Aclump == Aclump.dict.end())
2533 Aclump.push_back(Ql,Qr,Mtmp);
2537 Aclump.block[it_Aclump->second] += Mtmp;
2545 auto [U,Sigma,Vdag] = Aclump.truncateSVD(min_Nsv,max_Nsv,eps_truncWeight,truncWeight,S,SVspec,
false,
false);
2548 Biped<Symmetry,Eigen::Matrix<Scalar,-1,-1> > left,right;
2572 left = U.contract(Sigma);
2577 for (
const auto &[ql, dim_l, plain] : leftBasis)
2578 for (
size_t s1=0; s1<qloc_l.size(); s1++)
2580 auto Qls = Symmetry::reduceSilent(ql,qloc_l[s1]);
2581 for (
const auto &Ql:Qls)
2583 auto it_left = left.dict.find({Ql,Ql});
2584 if (it_left == left.dict.end()) {
continue;}
2585 if (Ql > qtop or Ql < qbot) {
continue;}
2586 Eigen::Matrix<Scalar,-1,-1> Mtmp(leftBasis.
inner_dim(ql),left.block[it_left->second].cols());
2589 Mtmp = left.block[it_left->second].block(left1, 0, leftBasis.
inner_dim(ql), left.block[it_left->second].cols());
2590 auto it_A = Al[s1].dict.find({ql,Ql});
2591 if (it_A == Al[s1].dict.end())
2593 Al[s1].push_back(ql,Ql,Mtmp);
2597 Al[s1].block[it_A->second] += Mtmp;
2603 for (
const auto &[qr, dim_r, plain] : rightBasis)
2604 for (
size_t s2=0; s2<qloc_r.size(); s2++)
2606 auto Qrs = Symmetry::reduceSilent(qr,Symmetry::flip(qloc_r[s2]));
2607 for (
const auto &Qr:Qrs)
2609 auto it_right = right.dict.find({Qr,Qr});
2610 if (it_right == right.dict.end()) {
continue;}
2611 if (Qr > qtop or Qr < qbot) {
continue;}
2612 Eigen::Matrix<Scalar,-1,-1> Mtmp(right.block[it_right->second].rows(),rightBasis.
inner_dim(qr));
2613 array<qarray<Symmetry::Nq>,2> source = {qr, Symmetry::flip(qloc_r[s2])};
2616 Mtmp = Symmetry::coeff_splitAA(Qr,qr,qloc_r[s2])*right.block[it_right->second].block(0, left2, right.block[it_right->second].rows(), rightBasis.
inner_dim(qr));
2619 auto it_A = Ar[s2].dict.find({Qr,qr});
2620 if (it_A == Al[s2].dict.end())
2622 Ar[s2].push_back(Qr,qr,Mtmp);
2626 Ar[s2].block[it_A->second] += Mtmp;
void addBottom(const MatrixType1 &Min, MatrixType2 &Mout)
void addRight(const MatrixType1 &Min, MatrixType2 &Mout)
void contract_AAAA(const vector< Biped< Symmetry, Matrix< Scalar, Dynamic, Dynamic > > > &A1, vector< qarray< Symmetry::Nq > > qloc1, const vector< Biped< Symmetry, Matrix< Scalar, Dynamic, Dynamic > > > &A2, vector< qarray< Symmetry::Nq > > qloc2, const vector< Biped< Symmetry, Matrix< Scalar, Dynamic, Dynamic > > > &A3, vector< qarray< Symmetry::Nq > > qloc3, const vector< Biped< Symmetry, Matrix< Scalar, Dynamic, Dynamic > > > &A4, vector< qarray< Symmetry::Nq > > qloc4, boost::multi_array< Biped< Symmetry, Matrix< Scalar, Dynamic, Dynamic > >, 4 > &Aquartett)
void contract_AA(const vector< Biped< Symmetry, Matrix< Scalar, Dynamic, Dynamic > > > &A1, const vector< qarray< Symmetry::Nq > > &qloc1, const vector< Biped< Symmetry, Matrix< Scalar, Dynamic, Dynamic > > > &A2, const vector< qarray< Symmetry::Nq > > &qloc2, const qarray< Symmetry::Nq > &Qtop, const qarray< Symmetry::Nq > &Qbot, vector< Biped< Symmetry, Matrix< Scalar, Dynamic, Dynamic > > > &Apair, bool DRY=false)
void contract_AA2(const vector< Biped< Symmetry, Matrix< Scalar, Dynamic, Dynamic > > > &A1, const vector< qarray< Symmetry::Nq > > &qloc1, const vector< Biped< Symmetry, Matrix< Scalar, Dynamic, Dynamic > > > &A2, const vector< qarray< Symmetry::Nq > > &qloc2, vector< Biped< Symmetry, Matrix< Scalar, Dynamic, Dynamic > > > &Apair, bool DRY=false)
void contract_C0(vector< qarray< Symmetry::Nq > > qloc, vector< qarray< Symmetry::Nq > > qOp, const vector< vector< vector< Biped< Symmetry, MpoMatrixType > > > > &W, const vector< Biped< Symmetry, MatrixType > > &Aket, vector< Tripod< Symmetry, MatrixType > > &Cnext)
vector< Biped< Symmetry, Matrix< Scalar, Dynamic, Dynamic > > > extend_A(const vector< Biped< Symmetry, Matrix< Scalar, Dynamic, Dynamic > > > &A, const vector< qarray< Symmetry::Nq > > &qloc)
void contract_GRALF(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, Biped< Symmetry, Matrix< Scalar, Dynamic, Dynamic > > &Tout, DMRG::DIRECTION::OPTION DIR)
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())
void split_AA2(DMRG::DIRECTION::OPTION DIR, const Qbasis< Symmetry > &locBasis, const vector< Biped< Symmetry, Matrix< Scalar, Dynamic, Dynamic > > > &Apair, const vector< qarray< Symmetry::Nq > > &qloc_l, vector< Biped< Symmetry, Matrix< Scalar, Dynamic, Dynamic > > > &Al, const vector< qarray< Symmetry::Nq > > &qloc_r, vector< Biped< Symmetry, Matrix< Scalar, Dynamic, Dynamic > > > &Ar, const qarray< Symmetry::Nq > &qtop, const qarray< Symmetry::Nq > &qbot, double eps_svd, size_t min_Nsv, size_t max_Nsv)
void contract_C(vector< qarray< Symmetry::Nq > > qloc, vector< qarray< Symmetry::Nq > > qOp, const vector< Biped< Symmetry, MatrixType > > &Abra, const vector< vector< vector< Biped< Symmetry, MpoMatrixType > > > > &W, const vector< Biped< Symmetry, MatrixType > > &Aket, const vector< Tripod< Symmetry, MatrixType > > &C, vector< Tripod< Symmetry, MatrixType > > &Cnext)
void split_AA(DMRG::DIRECTION::OPTION DIR, const vector< Biped< Symmetry, Matrix< Scalar, Dynamic, Dynamic > > > &Apair, const vector< qarray< Symmetry::Nq > > &qloc_l, vector< Biped< Symmetry, Matrix< Scalar, Dynamic, Dynamic > > > &Al, const vector< qarray< Symmetry::Nq > > &qloc_r, vector< Biped< Symmetry, Matrix< Scalar, Dynamic, Dynamic > > > &Ar, const qarray< Symmetry::Nq > &qtop, const qarray< Symmetry::Nq > &qbot, double eps_svd, size_t min_Nsv, size_t max_Nsv)
void optimal_multiply(Scalar alpha, const MatrixTypeA &A, const MatrixTypeB &B, const MatrixTypeC &C, MatrixTypeR &result, bool DEBUG=false)
bool AWWA(qarray< Symmetry::Nq > Lin, qarray< Symmetry::Nq > Lout, qarray< Symmetry::Nq > Lbot, qarray< Symmetry::Nq > Ltop, qarray< Symmetry::Nq > qloc1, qarray< Symmetry::Nq > qloc2, qarray< Symmetry::Nq > qloc3, qarray< Symmetry::Nq > qOpBot, qarray< Symmetry::Nq > qOpTop, const Biped< Symmetry, MatrixType > &Abra, const Biped< Symmetry, MatrixType > &Aket, const Biped< Symmetry, MpoMatrixType > &Wbot, const Biped< Symmetry, MpoMatrixType > &Wtop, tuple< qarray4< Symmetry::Nq >, size_t, size_t, size_t, size_t > &result)
bool LAWA(const qarray< Symmetry::Nq > &Lin, const qarray< Symmetry::Nq > &Lout, const qarray< Symmetry::Nq > &Lmid, const qarray< Symmetry::Nq > &qloc1, const qarray< Symmetry::Nq > &qloc2, const qarray< Symmetry::Nq > &qOp, const Biped< Symmetry, MatrixType > &Abra, const Biped< Symmetry, MatrixType > &Aket, const Biped< Symmetry, MatrixType2 > &W, vector< tuple< qarray3< Symmetry::Nq >, size_t, size_t, size_t > > &result)
bool LAA(qarray< Symmetry::Nq > Lin, qarray< Symmetry::Nq > Lout, size_t s, vector< qarray< Symmetry::Nq > > qloc, const vector< Biped< Symmetry, MatrixType > > &Abra, const vector< Biped< Symmetry, MatrixType > > &Aket, vector< tuple< qarray2< Symmetry::Nq >, size_t, size_t > > &result)
vector< qarray< Symmetry::Nq > > calc_qsplit(const vector< Biped< Symmetry, Eigen::Matrix< Scalar, Dynamic, Dynamic > > > &A1, const vector< qarray< Symmetry::Nq > > &qloc1, const vector< Biped< Symmetry, Eigen::Matrix< Scalar, Dynamic, Dynamic > > > &A2, vector< qarray< Symmetry::Nq > > qloc2, const qarray< Symmetry::Nq > &Qtop, const qarray< Symmetry::Nq > &Qbot)
bool AAR(qarray< Symmetry::Nq > Rin, qarray< Symmetry::Nq > Rout, size_t s, vector< qarray< Symmetry::Nq > > qloc, const vector< Biped< Symmetry, MatrixType > > &Abra, const vector< Biped< Symmetry, MatrixType > > &Aket, vector< tuple< qarray2< Symmetry::Nq >, size_t, size_t > > &result)
bool AWAR(const qarray< Symmetry::Nq > &Rin, const qarray< Symmetry::Nq > &Rout, const qarray< Symmetry::Nq > &Rmid, const qarray< Symmetry::Nq > &qloc1, const qarray< Symmetry::Nq > &qloc2, const qarray< Symmetry::Nq > &qOp, const Biped< Symmetry, MatrixType > &Abra, const Biped< Symmetry, MatrixType > &Aket, const Biped< Symmetry, MatrixType2 > &W, vector< tuple< qarray3< Symmetry::Nq >, size_t, size_t, size_t > > &result)
Hamiltonian sum(const Hamiltonian &H1, const Hamiltonian &H2, DMRG::VERBOSITY::OPTION VERBOSITY=DMRG::VERBOSITY::SILENT)
void swap(Mps< Symmetry, Scalar > &V1, Mps< Symmetry, Scalar > &V2)
const std::vector< qType > qs() const
qType find(const std::string &ident) const
Eigen::Index inner_num(const Eigen::Index &outer_num) const
Qbasis< Symmetry > combine(const Qbasis< Symmetry > &other, bool FLIP=false) const
std::vector< std::tuple< qType, Eigen::Index, Basis > >::const_iterator cbegin() const
Eigen::Index leftOffset(const qType &qnew, const std::array< qType, 2 > &qold, const std::array< Eigen::Index, 2 > &plain_old) const
void pullData(const vector< Biped< Symmetry, MatrixType > > &A, const Eigen::Index &leg)
std::vector< std::tuple< qType, Eigen::Index, Basis > >::const_iterator cend() const
Eigen::Index outer_num(const qType &q) const
Eigen::Index inner_dim(const Eigen::Index &num_in) 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
std::array< qarray< Nq >, 3 > qarray3
std::unordered_map< std::array< qType, 2 >, std::size_t > dict
std::vector< MatrixType_ > block
void outerResize(const Biped< Symmetry, OtherMatrixType > Brhs)
Biped< Symmetry, MatrixType_ > contract(const Biped< Symmetry, MatrixType_ > &A, const contract::MODE MODE=contract::MODE::UNITY) const
void push_back(qType qin, qType qout, const MatrixType_ &M)
unordered_map< std::array< qType, Nlegs >, size_t > dict
qType mid(size_t q) const
qType top(size_t q) const
qType out(size_t q) const
void push_back(std::array< qType, Nlegs > quple, const boost::multi_array< MatrixType, LEGLIMIT > &M)
vector< boost::multi_array< MatrixType, LEGLIMIT > > block
qType bot(size_t q) const