1#ifndef STRAWBERRY_MPSCOMPRESSOR_WITH_Q
2#define STRAWBERRY_MPSCOMPRESSOR_WITH_Q
4#ifndef DMRG_POLYCOMPRESS_TOL
5#define DMRG_POLYCOMPRESS_TOL 1e-4
8#ifndef DMRG_POLYCOMPRESS_MIN
9#define DMRG_POLYCOMPRESS_MIN 1
12#ifndef DMRG_POLYCOMPRESS_MAX
13#define DMRG_POLYCOMPRESS_MAX 32
16#define MPSQCOMPRESSOR_DONT_USE_OPENMP
19#include "termcolor.hpp"
23#include "LanczosSolver.h"
36template<
typename Symmetry,
typename Scalar,
typename MpoScalar=
double>
55 double memory (MEMUNIT memunit=GB)
const;
73 size_t Minit,
size_t Mincr=100,
size_t Mlimit=10000,
double tol=1e-4,
size_t max_halfsweeps=40,
size_t min_halfsweeps=1);
93 template<
typename MpOperator>
96 size_t max_halfsweeps=100,
size_t min_halfsweeps=1, std::size_t savePeriod = 0,
97 std::string saveName=
"backup",
bool MEASURE_DISTANCE=
true,
const MpOperator * HdagH = NULL
119 template<
typename MpOperator>
126 size_t Minit,
size_t Mincr=100,
size_t Mlimit=10000,
double tol=1e-4,
size_t max_halfsweeps=40,
size_t min_halfsweeps=1);
135 vector<PivotOverlap1<Symmetry,Scalar> >
Env;
153 vector<PivotMatrix1<Symmetry,Scalar,MpoScalar> >
Heff;
155 template<
typename MpOperator>
158 template<
typename MpOperator>
162 template<
typename MpOperator>
165 template<
typename MpOperator>
168 template<
typename MpOperator>
172 template<
typename MpOperator>
175 template<
typename MpOperator>
179 template<
typename MpOperator>
181 bool RANDOMIZE =
false);
183 template<
typename MpOperator>
187 vector<vector<PivotOverlap1<Symmetry,Scalar> > >
Envs;
212 template<
typename MpOperator>
235template<
typename Symmetry,
typename Scalar,
typename MpoScalar>
240 ss <<
"MpsCompressor: ";
241 ss <<
"Mcutoff=" << Mcutoff;
242 if (Mcutoff != Mcutoff_new)
244 ss <<
"→" << Mcutoff_new <<
", ";
248 ss <<
" (not resized), ";
250 ss <<
"Mmax=" << Mmax;
251 if (Mmax != Mmax_new)
253 ss <<
"→" << Mmax_new <<
", ";
257 ss <<
" (not changed), ";
260 ss <<
"|Vlhs-Vrhs|^2=";
261 if (sqdist <= tol) {ss << termcolor::green;}
262 else {ss << termcolor::yellow;}
263 ss << termcolor::reset << sqdist <<
", ";
264 ss <<
"halfsweeps=" << N_halfsweeps <<
", ";
265 ss <<
"mem=" << round(memory(GB),3) <<
"GB";
269template<
typename Symmetry,
typename Scalar,
typename MpoScalar>
274 ss <<
"t[s]=" << termcolor::bold << t_tot << termcolor::reset
275 <<
", opt=" << round(t_opt/t_tot*100.,0) <<
"%"
276 <<
", sweep=" << round(t_sweep/t_tot*100.) <<
"%"
277 <<
", LR=" << round(t_LR/t_tot*100.) <<
"%";
280 ss <<
", ohead=" << round(t_ohead/t_tot*100.) <<
"%";
284 ss <<
", AA=" << round(t_AA/t_tot*100.) <<
"%";
289template<
typename Symmetry,
typename Scalar,
typename MpoScalar>
291memory (MEMUNIT memunit)
const
294 for (
size_t l=0; l<Env.size(); ++l)
296 res += Env[l].L.memory(memunit);
297 res += Env[l].R.memory(memunit);
299 for (
size_t l=0; l<Heff.size(); ++l)
301 res += Heff[l].memory(memunit);
306template<
typename Symmetry,
typename Scalar,
typename MpoScalar>
307template<
typename MpOperator>
312 assert(pivot == 0 or pivot==1 or pivot==N_sites-2 or pivot==N_sites-1);
320 build_RW(0,Vout,H,Vin1);
324 build_R (0,Vout, Vin2);
327 else if (pivot==N_sites-2)
333 build_LW(N_sites-1,Vout,H,Vin1);
337 build_L (N_sites-1,Vout, Vin2);
342template<
typename Symmetry,
typename Scalar,
typename MpoScalar>
346 assert(pivot == 0 or pivot==1 or pivot==N_sites-2 or pivot==N_sites-1);
357 else if (pivot==N_sites-2)
363 build_L(N_sites-1,Vout,Vin);
368template<
typename Symmetry,
typename Scalar,
typename MpoScalar>
372 assert(pivot == 0 or pivot==1 or pivot==N_sites-2 or pivot==N_sites-1);
383 else if (pivot==N_sites-2)
389 build_L(N_sites-1,Vout,Vin);
398template<
typename Symmetry,
typename Scalar,
typename MpoScalar>
401 size_t Minit,
size_t Mincr,
size_t Mlimit,
double tol_input,
size_t max_halfsweeps,
size_t min_halfsweeps)
409 Mcutoff = Mcutoff_new = Minit;
421 for (
size_t l=0; l<N_sites; ++l)
425 Env[N_sites-1].R.setIdentity(Vout.
outBasis(N_sites-1), Vin.
outBasis(N_sites-1));
431 size_t halfSweepRange = N_sites;
435 lout << Chronos.info(
"preparation stateCompress") << endl;
439 while ((sqdist > tol and N_halfsweeps < max_halfsweeps) or N_halfsweeps < min_halfsweeps or N_halfsweeps%2 != 0)
447 Stopwatch<> FullSweepTimer;
450 if (N_halfsweeps%4 == 0 and N_halfsweeps > 1)
452 sweep_to_edge(Vin,Vout,
true);
455 for (
size_t j=1; j<=halfSweepRange; ++j)
457 turnaround(pivot, N_sites, CURRENT_DIRECTION);
458 if (N_halfsweeps%4 == 0 and N_halfsweeps > 1)
460 stateOptimize2(Vin,Vout);
464 stateOptimize1(Vin,Vout);
468 halfSweepRange = N_sites-1;
473 assert(!std::isnan(sqdist));
477 lout <<
" distance^2=";
478 if (sqdist <= tol) {lout << termcolor::green;}
479 else {lout << termcolor::yellow;}
480 lout << sqdist << termcolor::reset <<
", ";
481 t_tot = FullSweepTimer.time();
482 lout << t_info() << endl;
485 if (N_halfsweeps%4 == 0 and
487 N_halfsweeps != max_halfsweeps and
490 auto max_Nsv_old = Vout.
max_Nsv;
496 lout <<
"resize: " << max_Nsv_old <<
"→" << Vout.
max_Nsv << endl;
504 sweep_to_edge(Vin,Vout,
false);
507template<
typename Symmetry,
typename Scalar,
typename MpoScalar>
511 assert(Vout.
pivot == 0 or Vout.
pivot == N_sites-1 or Vout.
pivot == -1);
513 if (Vout.
pivot == N_sites-1 or Vout.
pivot == -1)
515 for (
int l=N_sites-1; l>0; --l)
518 build_R(l-1,Vout,Vin,
true);
522 else if (Vout.
pivot == 0)
524 for (
size_t l=0; l<N_sites-1; ++l)
527 build_L(l+1,Vout,Vin,
true);
534template<
typename Symmetry,
typename Scalar,
typename MpoScalar>
539 Stopwatch<> OptTimer;
540 LRxV(Env[pivot], Ain, Aout);
541 t_opt += OptTimer.time();
543 for (
size_t s=0; s<Aout.
size(); ++s)
545 Aout[s] = Aout[s].cleaned();
549template<
typename Symmetry,
typename Scalar,
typename MpoScalar>
554 stateOptimize1(Vin,Vout,Aout);
555 Vout.
A[pivot] = Aout.
data;
568 Stopwatch<> SweepTimer;
570 t_sweep += SweepTimer.time();
575template<
typename Symmetry,
typename Scalar,
typename MpoScalar>
588 t_AA += AAtimer.time();
590 Stopwatch<> OptTimer;
592 LRxV(Env2, ApairIn, ApairOut);
593 t_opt += OptTimer.time();
595 for (
size_t s=0; s<ApairOut.
data.size(); ++s)
597 ApairOut.
data[s] = ApairOut.
data[s].cleaned();
601template<
typename Symmetry,
typename Scalar,
typename MpoScalar>
606 stateOptimize2(Vin,Vout,Apair);
608 Stopwatch<> SweepTimer;
610 t_sweep += SweepTimer.time();
615template<
typename Symmetry,
typename Scalar,
typename MpoScalar>
620 contract_L(Env[loc-1].L, Vbra.
A[loc-1], Vket.
A[loc-1], Vket.
locBasis(loc-1), Env[loc].L, RANDOMIZE,
true);
621 t_LR += LRtimer.time();
624template<
typename Symmetry,
typename Scalar,
typename MpoScalar>
629 contract_R(Env[loc+1].R, Vbra.
A[loc+1], Vket.
A[loc+1], Vket.
locBasis(loc+1), Env[loc].R, RANDOMIZE,
true);
630 t_LR += LRtimer.time();
637template<
typename Symmetry,
typename Scalar,
typename MpoScalar>
640 size_t Minit,
size_t Mincr,
size_t Mlimit,
double tol_input,
size_t max_halfsweeps,
size_t min_halfsweeps)
643 N_sites = Vin[0].length();
645 size_t N_vecs = Vin.size();
648 Mcutoff = Mcutoff_new = Minit;
651 Matrix<Scalar,Dynamic,Dynamic> overlapsVin(N_vecs,N_vecs);
652 #ifndef MPSQCOMPRESSOR_DONT_USE_OPENMP
653 #pragma omp parallel for
655 for (
int i=0; i<N_vecs; ++i)
656 for (
int j=0; j<=i; ++j)
658 overlapsVin(i,j) =
conjIfcomplex(factors[i]) * factors[j] *
dot(Vin[i],Vin[j]);
664 overlapsVin.template triangularView<Upper>() = overlapsVin.adjoint();
665 double overlapsVinSum =
isReal(overlapsVin.sum());
669 for (
int i=0; i<N_vecs; ++i)
672 Envs[i].resize(N_sites);
673 Envs[i][N_sites-1].R.setTarget(Vin[i].Qmultitarget());
674 Envs[i][0].L.setVacuum();
675 for (
size_t l=0; l<N_sites; ++l)
677 Envs[i][l].qloc = Vin[i].locBasis(l);
689 size_t halfSweepRange = N_sites;
691 if (CHOSEN_VERBOSITY>=2)
693 lout << Chronos.info(
"preparation lincomboCompress") << endl;
697 while ((sqdist > tol and N_halfsweeps < max_halfsweeps) or N_halfsweeps < min_halfsweeps or N_halfsweeps%2 != 0)
705 Stopwatch<> FullSweepTimer;
708 if (N_halfsweeps%4 == 0 and N_halfsweeps > 1)
711 sweep_to_edge(Vin,Vout,
true);
714 for (
size_t j=1; j<=halfSweepRange; ++j)
717 turnaround(pivot, N_sites, CURRENT_DIRECTION);
720 if (N_halfsweeps%4 == 0 and N_halfsweeps > 1)
722 vector<PivotVector<Symmetry,Scalar> > Apair(N_vecs);
724 stateOptimize2(Vin,Vout,Apair);
731 for (
int i=0; i<N_vecs; ++i)
732 for (
size_t s=0; s<Asum.
size(); ++s)
734 Asum[s].addScale(factors[i], Apair[i][s]);
738 for (
size_t s=0; s<Asum.
size(); ++s)
740 Asum[s] = Asum[s].cleaned();
744 Stopwatch<> SweepTimer;
748 t_sweep += SweepTimer.time();
753 vector<PivotVector<Symmetry,Scalar> > Ares(N_vecs);
755 stateOptimize1(Vin,Vout,Ares);
758 Stopwatch<> OheadTimer;
760 t_ohead += OheadTimer.time();
767 Vout /= sqrt(Vsqnorm);
773 for (
int i=0; i<N_vecs; ++i)
774 for (
size_t s=0; s<Asum.
size(); ++s)
776 Asum[s].addScale(factors[i], Ares[i][s]);
779 for (
size_t s=0; s<Asum.
size(); ++s)
781 Asum[s] = Asum[s].cleaned();
784 Vout.
A[pivot] = Asum.
data;
786 Stopwatch<> SweepTimer;
788 t_sweep += SweepTimer.time();
795 halfSweepRange = N_sites-1;
801 assert(!std::isnan(sqdist));
803 if (CHOSEN_VERBOSITY>=2)
805 lout <<
" distance^2=";
806 if (sqdist <= tol) {lout << termcolor::green;}
807 else {lout << termcolor::yellow;}
808 lout << sqdist << termcolor::reset <<
", ";
809 t_tot = FullSweepTimer.time();
810 lout << t_info() << endl;
813 if (N_halfsweeps%4 == 0 and
815 N_halfsweeps != max_halfsweeps and
818 auto max_Nsv_old = Vout.
max_Nsv;
824 lout <<
"resize: " << max_Nsv_old <<
"→" << Vout.
max_Nsv << endl;
832 sweep_to_edge(Vin,Vout,
false);
835template<
typename Symmetry,
typename Scalar,
typename MpoScalar>
839 assert(Vout.
pivot == 0 or Vout.
pivot == N_sites-1 or Vout.
pivot == -1);
842 if (Vout.
pivot == N_sites-1 or
845 for (
int l=N_sites-1; l>0; --l)
848 build_R(l-1,Vout,Vin,
true);
852 else if (Vout.
pivot == 0)
854 for (
size_t l=0; l<N_sites-1; ++l)
857 build_L(l+1,Vout,Vin,
true);
864template<
typename Symmetry,
typename Scalar,
typename MpoScalar>
868 #ifndef MPSQCOMPRESSOR_DONT_USE_OPENMP
869 #pragma omp parallel for
871 for (
int i=0; i<Vin.size(); ++i)
874 Stopwatch<> OptTimer;
875 LRxV(Envs[i][pivot], Ain, Aout[i]);
876 t_opt += OptTimer.time();
878 for (
size_t s=0; s<Aout[i].size(); ++s)
880 Aout[i][s] = Aout[i][s].cleaned();
885template<
typename Symmetry,
typename Scalar,
typename MpoScalar>
889 #ifndef MPSQCOMPRESSOR_DONT_USE_OPENMP
890 #pragma omp parallel for
892 for (
int i=0; i<Vin.size(); ++i)
896 Vin[i].
A[loc2()], Vin[i].locBasis(loc2()),
897 Vin[i].QoutTop[loc1()], Vin[i].QoutBot[loc1()]);
903 t_AA += AAtimer.time();
905 Stopwatch<> OptTimer;
907 LRxV(Env2, ApairIn, ApairOut[i]);
908 t_opt += OptTimer.time();
910 for (
size_t s=0; s<ApairOut[i].data.size(); ++s)
912 ApairOut[i].data[s] = ApairOut[i].data[s].cleaned();
917template<
typename Symmetry,
typename Scalar,
typename MpoScalar>
922 #ifndef MPSQCOMPRESSOR_DONT_USE_OPENMP
923 #pragma omp parallel for
925 for (
int i=0; i<Vket.size(); ++i)
927 contract_L(Envs[i][loc-1].L, Vbra.
A[loc-1], Vket[i].A[loc-1], Vket[i].locBasis(loc-1), Envs[i][loc].L, RANDOMIZE,
true);
929 t_LR += LRtimer.time();
932template<
typename Symmetry,
typename Scalar,
typename MpoScalar>
937 #ifndef MPSQCOMPRESSOR_DONT_USE_OPENMP
938 #pragma omp parallel for
940 for (
int i=0; i<Vket.size(); ++i)
942 contract_R(Envs[i][loc+1].R, Vbra.
A[loc+1], Vket[i].A[loc+1], Vket[i].locBasis(loc+1), Envs[i][loc].R, RANDOMIZE,
true);
944 t_LR += LRtimer.time();
947template<
typename Symmetry,
typename Scalar,
typename MpoScalar>
958template<
typename Symmetry,
typename Scalar,
typename MpoScalar>
959template<
typename MpOperator>
962 size_t Minit,
size_t Mincr,
size_t Mlimit,
double tol_input,
size_t max_halfsweeps,
size_t min_halfsweeps,
963 std::size_t savePeriod, std::string saveName,
bool MEASURE_DISTANCE,
const MpOperator * HdagH)
965 if (CHOSEN_VERBOSITY>=2)
967 lout << endl << termcolor::colorize << termcolor::bold
968 <<
"———————————————————————————————————————————prodCompress: |Φ> = H|Ψ>————————————————————————————————————————————"
969 << termcolor::reset << endl;
977 Mcutoff = Mcutoff_new = Minit;
979 if (H.Qtarget() == Symmetry::qvacuum())
990 Heff.resize(N_sites);
991 for (
int l=0; l<N_sites; ++l) Heff[l].Terms.resize(1);
992 Heff[0].Terms[0].L.setVacuum();
994 vector<qarray3<Symmetry::Nq> > Qt;
999 Heff[N_sites-1].Terms[0].R.setTarget(Qt);
1001 for (
size_t l=0; l<N_sites; ++l)
1003 Heff[l].Terms[0].W = H.W[l];
1011 if (MEASURE_DISTANCE)
1013 #ifndef MPSQCOMPRESSOR_DONT_USE_OPENMP
1014 #pragma omp parallel sections
1017 #ifndef MPSQCOMPRESSOR_DONT_USE_OPENMP
1029 avgHsqVin =
isReal(
avg(Vin,*HdagH,Vin));
1033 if (H.IS_HERMITIAN())
1039 avgHsqVin =
isReal(
avg(Vin,Hdag,H,Vin));
1046 prepSweep(H,Vin,Vout);
1048 size_t halfSweepRange = N_sites;
1050 if (CHOSEN_VERBOSITY>=2)
1052 lout << Chronos.info(
"• preparation prodCompress") << endl;
1053 size_t standard_precision = cout.precision();
1054 lout <<
"• initial state : " << Vout.
info() << endl;
1055 lout <<
"• bond dim. increase by ";
1056 cout << termcolor::underline;
1058 cout << termcolor::reset;
1060 cout << termcolor::underline;
1062 cout << termcolor::reset;
1063 lout <<
" half-sweeps" << endl;
1064 lout <<
"• make between ";
1065 cout << termcolor::underline;
1066 lout << min_halfsweeps;
1067 cout << termcolor::reset;
1069 cout << termcolor::underline;
1070 lout << max_halfsweeps;
1071 cout << termcolor::reset;
1072 lout <<
" half-sweep iterations" << endl;
1073 lout <<
"• convergence tolerance: ";
1074 cout << termcolor::underline;
1076 cout << termcolor::reset;
1077 lout << endl << endl;
1081 while ((sqdist > tol and N_halfsweeps < max_halfsweeps) or N_halfsweeps < min_halfsweeps)
1089 Stopwatch<> FullSweepTimer;
1092 if (N_halfsweeps%4 == 0 and N_halfsweeps > 1)
1094 sweep_to_edge(H,Vin,Vin,Vout,
false,
true);
1100 for (
size_t j=1; j<=halfSweepRange; ++j)
1102 turnaround(pivot, N_sites, CURRENT_DIRECTION);
1103 if (N_halfsweeps%4 == 0 and N_halfsweeps > 1)
1105 prodOptimize2(H,Vin,Vout);
1109 prodOptimize1(H,Vin,Vout);
1113 halfSweepRange = N_sites-1;
1116 if (MEASURE_DISTANCE)
1118 cout <<
"avgHsqVin=" << avgHsqVin << endl;
1119 cout <<
"Vout.squaredNorm()=" << Vout.
squaredNorm() << endl;
1121 assert(!std::isnan(sqdist));
1126 sqdist = abs(norm_new-norm_old);
1129 if (CHOSEN_VERBOSITY>=2)
1131 cout << termcolor::underline;
1132 lout <<
"half-sweeps=" << N_halfsweeps;
1133 cout << termcolor::reset;
1134 size_t standard_precision = cout.precision();
1135 lout <<
", distance^2=";
1136 if (sqdist <= tol) {cout << termcolor::green;}
1137 else {cout << termcolor::yellow;}
1139 cout << termcolor::reset;
1141 t_tot = FullSweepTimer.time();
1142 lout << t_info() << endl;
1143 lout << Vout.
info() << endl;
1146 bool RESIZED =
false;
1147 if (N_halfsweeps%4 == 0 and
1148 N_halfsweeps > 1 and
1149 N_halfsweeps != max_halfsweeps and
1154 auto max_Nsv_old = Vout.
max_Nsv;
1160 lout <<
"resize: " << max_Nsv_old <<
"→" << Vout.
max_Nsv << endl;
1166 #ifdef USE_HDF5_STORAGE
1167 if (savePeriod != 0 and N_halfsweeps%savePeriod == 0)
1169 Vout.save(saveName,H.info());
1170 cout << termcolor::green;
1171 lout <<
"Saved state to: " << saveName;
1172 cout << termcolor::reset;
1177 #ifdef COMPRESSOR_RESTART_FROM_RANDOM
1178 if (N_halfsweeps == max_halfsweeps/2 and sqdist > tol)
1180 cout << termcolor::red;
1181 lout <<
"Warning: Could not reach tolerance, restarting from random!";
1182 cout << termcolor::reset;
1184 prepSweep(H,Vin,Vout,
true);
1187 if (CHOSEN_VERBOSITY>=2)
1196 Scalar factor_cgc = 1.;
1198 sweep_to_edge(H,Vin,Vin,Vout,
false,
false);
1201template<
typename Symmetry,
typename Scalar,
typename MpoScalar>
1202template<
typename MpOperator>
1206 assert(Vout.
pivot == 0 or Vout.
pivot == N_sites-1 or Vout.
pivot == -1);
1220 if (Vout.
pivot == N_sites-1 or Vout.
pivot == -1)
1222 for (
int l=N_sites-1; l>0; --l)
1225 build_RW(l-1,Vout,H,Vin,RANDOMIZE);
1229 else if (Vout.
pivot == 0)
1231 for (
size_t l=0; l<N_sites-1; ++l)
1234 build_LW(l+1,Vout,H,Vin,RANDOMIZE);
1242template<
typename Symmetry,
typename Scalar,
typename MpoScalar>
1243template<
typename MpOperator>
1247 Stopwatch<> OheadTimer;
1248 precalc_blockStructure (Heff[pivot].Terms[0].L, Vout.
A[pivot], Heff[pivot].Terms[0].W, Vin.
A[pivot], Heff[pivot].Terms[0].R,
1249 H.locBasis(pivot), H.opBasis(pivot),
1250 Heff[pivot].qlhs, Heff[pivot].qrhs, Heff[pivot].factor_cgcs);
1254 t_ohead += OheadTimer.time();
1256 Stopwatch<> OptTimer;
1257 OxV(Heff[pivot], Ain, Aout);
1258 t_opt += OptTimer.time();
1261template<
typename Symmetry,
typename Scalar,
typename MpoScalar>
1262template<
typename MpOperator>
1267 prodOptimize1(H,Vin,Vout,Aout);
1268 Vout.
A[pivot] = Aout.
data;
1271 Stopwatch<> OheadTimer;
1273 t_ohead += OheadTimer.time();
1280 Vout /= sqrt(Vsqnorm);
1283 Stopwatch<> SweepTimer;
1285 t_sweep += SweepTimer.time();
1291template<
typename Symmetry,
typename Scalar,
typename MpoScalar>
1292template<
typename MpOperator>
1296 Stopwatch<> AAtimer;
1305 t_AA += AAtimer.time();
1308 H.W[loc1()], H.W[loc2()],
1309 H.locBasis(loc1()), H.locBasis(loc2()),
1310 H.opBasis (loc1()), H.opBasis (loc2()));
1312 Stopwatch<> OheadTimer;
1314 H.locBasis(loc1()), H.locBasis(loc2()), H.opBasis(loc1()), H.opBasis(loc2()),
1316 t_ohead += OheadTimer.time();
1318 Stopwatch<> OptTimer;
1319 OxV(Heff2, ApairIn, ApairOut);
1320 t_opt += OptTimer.time();
1322 for (
size_t s=0; s<ApairOut.
data.size(); ++s)
1324 ApairOut.
data[s] = ApairOut.
data[s].cleaned();
1328template<
typename Symmetry,
typename Scalar,
typename MpoScalar>
1329template<
typename MpOperator>
1333 Stopwatch<> Chronos;
1335 Stopwatch<> OptTimer;
1337 prodOptimize2(H,Vin,Vout,Apair);
1338 t_opt += OptTimer.time();
1340 Stopwatch<> SweepTimer;
1342 t_sweep += SweepTimer.time();
1349template<
typename Symmetry,
typename Scalar,
typename MpoScalar>
1350template<
typename MpOperator>
1354 Stopwatch<> LRtimer;
1355 contract_L(Heff[loc-1].Terms[0].L, Vbra.
A[loc-1], H.W[loc-1], Vket.
A[loc-1], H.locBasis(loc-1), H.opBasis(loc-1), Heff[loc].Terms[0].L, RANDOMIZE);
1356 t_LR += LRtimer.time();
1359template<
typename Symmetry,
typename Scalar,
typename MpoScalar>
1360template<
typename MpOperator>
1364 Stopwatch<> LRtimer;
1365 contract_R(Heff[loc+1].Terms[0].R, Vbra.
A[loc+1], H.W[loc+1], Vket.
A[loc+1], H.locBasis(loc+1), H.opBasis(loc+1), Heff[loc].Terms[0].R, RANDOMIZE);
1366 t_LR += LRtimer.time();
1369template<
typename Symmetry,
typename Scalar,
typename MpoScalar>
1370template<
typename MpOperator>
1373 size_t Minit,
size_t Mincr,
size_t Mlimit,
double tol_input,
size_t max_halfsweeps,
size_t min_halfsweeps)
1377 Stopwatch<> Chronos;
1380 Mcutoff = Mcutoff_new = Minit;
1385 if (CHOSEN_VERBOSITY>=2)
1387 lout <<
"Vin1: " << Vin1.
info() << endl;
1388 lout <<
"Vin2: " << Vin2.
info() << endl;
1405 Heff.resize(N_sites);
1409 for (
size_t l=0; l<N_sites; ++l)
1425 Env.resize(N_sites);
1426 for (
size_t l=0; l<N_sites; ++l)
1430 Env[N_sites-1].R.setIdentity(Vin2.
outBasis(N_sites-1), Vout.
outBasis(N_sites-1));
1433 double avgHsqV1, sqnormV2, overlapV12;
1436 #ifndef MPSQCOMPRESSOR_DONT_USE_OPENMP
1437 #pragma omp parallel sections
1440 #ifndef MPSQCOMPRESSOR_DONT_USE_OPENMP
1446 avgHsqV1 = (H.maxPower()>=2)?
isReal(
avg(Vin1,H,Vin1,2)) :
isReal(
avg(Vin1,H,H,Vin1));
1450 avgHsqV1 =
avg_hetero(Vin1,H,Vin1,
true,
true);
1453 #ifndef MPSQCOMPRESSOR_DONT_USE_OPENMP
1466 #ifndef MPSQCOMPRESSOR_DONT_USE_OPENMP
1470 prepSweep(H,Vin1,Vin2,Vout);
1474 size_t halfSweepRange = N_sites;
1476 if (CHOSEN_VERBOSITY>=2)
1478 lout << Chronos.info(
"preparation polyCompress") << endl;
1491 while ((sqdist > tol and N_halfsweeps < max_halfsweeps) or N_halfsweeps < min_halfsweeps)
1499 Stopwatch<> FullSweepTimer;
1502 if (N_halfsweeps%4 == 0 and N_halfsweeps > 1)
1504 sweep_to_edge(H,Vin1,Vin2,Vout,
true,
true);
1507 for (
size_t j=1; j<=halfSweepRange; ++j)
1509 turnaround(pivot, N_sites, CURRENT_DIRECTION);
1510 Stopwatch<> Chronos;
1512 if (N_halfsweeps%4 == 0 and N_halfsweeps > 1)
1515 prodOptimize2(H,Vin1,Vout,Apair1);
1518 stateOptimize2(Vin2,Vout,Apair2);
1520 for (
size_t s=0; s<Apair1.
size(); ++s)
1522 Apair1[s].addScale(-polyB, Apair2[s]);
1523 Apair1[s] = Apair1[s].cleaned();
1526 Stopwatch<> SweepTimer;
1528 t_sweep += SweepTimer.time();
1534 prodOptimize1(H,Vin1,Vout,A1);
1537 stateOptimize1(Vin2,Vout,A2);
1539 for (
size_t s=0; s<A1.
size(); ++s)
1541 A1[s].addScale(-polyB, A2[s]);
1542 A1[s] = A1[s].cleaned();
1544 Vout.
A[pivot] = A1.
data;
1546 Stopwatch<> SweepTimer;
1548 t_sweep += SweepTimer.time();
1552 build_LRW(H,Vin1,Vin2,Vout);
1555 halfSweepRange = N_sites-1;
1563 double sqdist_ = sqdist;
1564 sqdist = abs(avgHsqV1 - Vout.
squaredNorm() + polyB*polyB*sqnormV2 - 2.*polyB*overlapV12);
1566 assert(!std::isnan(sqdist));
1568 if (CHOSEN_VERBOSITY>=2)
1570 lout <<
" distance^2=";
1571 if (sqdist <= tol) {lout << termcolor::green;}
1572 else {lout << termcolor::yellow;}
1573 lout << sqdist << termcolor::reset <<
", ";
1574 t_tot = FullSweepTimer.time();
1575 lout << t_info() << endl;
1578 bool RESIZED =
false;
1579 if (N_halfsweeps%4 == 0 and
1580 N_halfsweeps > 1 and
1581 N_halfsweeps != max_halfsweeps and
1584 auto max_Nsv_old = Vout.
max_Nsv;
1590 lout <<
"resize: " << max_Nsv_old <<
"→" << Vout.
max_Nsv << endl;
1594 if (N_halfsweeps == max_halfsweeps/2 and sqdist > tol)
1596 lout << termcolor::red <<
"Warning: Could not reach tolerance, restarting from random!" << termcolor::reset << endl;
1597 prepSweep(H,Vin1,Vin2,Vout,
true);
1604 sweep_to_edge(H,Vin1,Vin2,Vout,
false,
false);
1607template<
typename Symmetry,
typename Scalar,
typename MpoScalar>
1608template<
typename MpOperator>
1612 assert(Vout.
pivot == 0 or Vout.
pivot == N_sites-1 or Vout.
pivot == -1);
1615 if (Vout.
pivot == N_sites-1)
1617 for (
int l=N_sites-1; l>0; --l)
1620 #ifndef MPSQCOMPRESSOR_DONT_USE_OPENMP
1621 #pragma omp parallel sections
1624 #ifndef MPSQCOMPRESSOR_DONT_USE_OPENMP
1628 build_RW(l-1,Vout,H,Vin1,RANDOMIZE);
1630 #ifndef MPSQCOMPRESSOR_DONT_USE_OPENMP
1634 build_R(l-1,Vout,Vin2,RANDOMIZE);
1640 else if (Vout.
pivot == 0 or Vout.
pivot == -1)
1642 for (
size_t l=0; l<N_sites-1; ++l)
1645 #ifndef MPSQCOMPRESSOR_DONT_USE_OPENMP
1646 #pragma omp parallel sections
1649 #ifndef MPSQCOMPRESSOR_DONT_USE_OPENMP
1653 build_LW(l+1,Vout,H,Vin1,RANDOMIZE);
1655 #ifndef MPSQCOMPRESSOR_DONT_USE_OPENMP
1659 build_L(l+1,Vout,Vin2,RANDOMIZE);
1668template<
typename Symmetry,
typename Scalar,
typename MpoScalar>
1669template<
typename MpOperator>
1673 #ifndef MPSQCOMPRESSOR_DONT_USE_OPENMP
1674 #pragma omp parallel sections
1677 #ifndef MPSQCOMPRESSOR_DONT_USE_OPENMP
1681 (CURRENT_DIRECTION ==
DMRG::DIRECTION::RIGHT)? build_LW(pivot,Vout,H,Vin1) : build_RW(pivot,Vout,H,Vin1);
1683 #ifndef MPSQCOMPRESSOR_DONT_USE_OPENMP
void precalc_blockStructure(const Tripod< Symmetry, Eigen::Matrix< Scalar, Dynamic, Dynamic > > &L, const vector< Biped< Symmetry, Eigen::Matrix< Scalar, Dynamic, Dynamic > > > &Abra, const vector< vector< vector< Biped< Symmetry, MpoMatrixType > > > > &W, const vector< Biped< Symmetry, Eigen::Matrix< Scalar, Dynamic, Dynamic > > > &Aket, const Tripod< Symmetry, Eigen::Matrix< Scalar, Dynamic, Dynamic > > &R, const vector< qarray< Symmetry::Nq > > &qloc, const vector< qarray< Symmetry::Nq > > &qOp, vector< std::array< size_t, 2 > > &qlhs, vector< vector< std::array< size_t, 6 > > > &qrhs, vector< vector< Scalar > > &factor_cgcs)
void turnaround(int pivot, size_t L, DMRG::DIRECTION::OPTION &DIR)
Flips the sweep direction when the edge is reached.
Scalar dot(const Mps< Symmetry, Scalar > &Vbra, const Mps< Symmetry, Scalar > &Vket)
void OxV(const Mpo< Symmetry, MpoScalar > &H, const Mpo< Symmetry, MpoScalar > &Hdag, const Mps< Symmetry, Scalar > &Vin, Mps< Symmetry, Scalar > &Vout, bool VERBOSE=true, double tol_compr=1e-4, int Mincr=100, int Mlimit=10000, int max_halfsweeps=100, int min_halfsweeps=1, bool MEASURE_DISTANCE=true)
Scalar avg_hetero(const Mps< Symmetry, Scalar > &Vbra, const Mpo< Symmetry, MpoScalar > &O, const Mps< Symmetry, Scalar > &Vket, bool USE_BOUNDARY=false, size_t usePower=1ul, const qarray< Symmetry::Nq > &Qmid=Symmetry::qvacuum())
Scalar avg(const Mps< Symmetry, Scalar > &Vbra, const Mpo< Symmetry, MpoScalar > &O, const Mps< Symmetry, Scalar > &Vket, size_t power_of_O=1ul, DMRG::DIRECTION::OPTION DIR=DMRG::DIRECTION::RIGHT, DMRG::VERBOSITY::OPTION CHOSEN_VERBOSITY=DMRG::VERBOSITY::SILENT)
void LRxV(const PivotOverlap1< Symmetry, Scalar > &H, const PivotVector< Symmetry, Scalar > &Vin, PivotVector< Symmetry, Scalar > &Vout)
double conjIfcomplex(double x)
#define DMRG_POLYCOMPRESS_TOL
#define DMRG_POLYCOMPRESS_MIN
#define DMRG_POLYCOMPRESS_MAX
void sweepStep(DMRG::DIRECTION::OPTION DIR, size_t loc, DMRG::BROOM::OPTION TOOL, PivotMatrixType *H=NULL, bool DISCARD_U_or_V=false)
void sweep(size_t loc, DMRG::BROOM::OPTION TOOL, PivotMatrixType *H=NULL)
void stateOptimize2(const Mps< Symmetry, Scalar > &Vin, const Mps< Symmetry, Scalar > &Vout, PivotVector< Symmetry, Scalar > &ApairOut)
void prodOptimize2(const MpOperator &H, const Mps< Symmetry, Scalar > &Vin, Mps< Symmetry, Scalar > &Vout)
Matrix< Scalar, Dynamic, Dynamic > MatrixType
void stateOptimize1(const Mps< Symmetry, Scalar > &Vin, const Mps< Symmetry, Scalar > &Vout, PivotVector< Symmetry, Scalar > &Aout)
void prodCompress(const MpOperator &H, const MpOperator &Hdag, const Mps< Symmetry, Scalar > &Vin, Mps< Symmetry, Scalar > &Vout, qarray< Symmetry::Nq > Qtot_input, size_t Minit, size_t Mincr=100, size_t Mlimit=10000, double tol=1e-4, size_t max_halfsweeps=100, size_t min_halfsweeps=1, std::size_t savePeriod=0, std::string saveName="backup", bool MEASURE_DISTANCE=true, const MpOperator *HdagH=NULL)
DMRG::VERBOSITY::OPTION CHOSEN_VERBOSITY
vector< vector< PivotOverlap1< Symmetry, Scalar > > > Envs
void lincomboCompress(const vector< Mps< Symmetry, Scalar > > &Vin, const vector< Scalar > &factors, Mps< Symmetry, Scalar > &Vout, const Mps< Symmetry, Scalar > &Vguess, size_t Minit, size_t Mincr=100, size_t Mlimit=10000, double tol=1e-4, size_t max_halfsweeps=40, size_t min_halfsweeps=1)
void polyCompress(const MpOperator &H, const Mps< Symmetry, Scalar > &Vin1, double polyB, const Mps< Symmetry, Scalar > &Vin2, Mps< Symmetry, Scalar > &Vout, size_t Minit, size_t Mincr=100, size_t Mlimit=10000, double tol=DMRG_POLYCOMPRESS_TOL, size_t max_halfsweeps=DMRG_POLYCOMPRESS_MAX, size_t min_halfsweeps=DMRG_POLYCOMPRESS_MIN)
void build_R(size_t loc, const Mps< Symmetry, Scalar > &Vbra, const Mps< Symmetry, Scalar > &Vket, bool RANDOMIZE=false)
double memory(MEMUNIT memunit=GB) const
vector< PivotMatrix1< Symmetry, Scalar, MpoScalar > > Heff
void stateCompress(const Mps< Symmetry, Scalar > &Vin, Mps< Symmetry, Scalar > &Vout, size_t Minit, size_t Mincr=100, size_t Mlimit=10000, double tol=1e-4, size_t max_halfsweeps=40, size_t min_halfsweeps=1)
void build_L(size_t loc, const Mps< Symmetry, Scalar > &Vbra, const Mps< Symmetry, Scalar > &Vket, bool RANDOMIZE=false)
string print_dist() const
void build_LRW(const MpOperator &H, const Mps< Symmetry, Scalar > &Vin1, const Mps< Symmetry, Scalar > &Vin2, Mps< Symmetry, Scalar > &Vout)
void sweep_to_edge(const Mps< Symmetry, Scalar > &Vin, Mps< Symmetry, Scalar > &Vout, bool BUILD_LR)
DMRG::DIRECTION::OPTION CURRENT_DIRECTION
void build_RW(size_t loc, const Mps< Symmetry, Scalar > &Vbra, const MpOperator &H, const Mps< Symmetry, Scalar > &Vket, bool RANDOMIZE=false)
MpsCompressor(DMRG::VERBOSITY::OPTION VERBOSITY=DMRG::VERBOSITY::SILENT)
void build_LW(size_t loc, const Mps< Symmetry, Scalar > &Vbra, const MpOperator &H, const Mps< Symmetry, Scalar > &Vket, bool RANDOMIZE=false)
void prodOptimize1(const MpOperator &H, const Mps< Symmetry, Scalar > &Vin, const Mps< Symmetry, Scalar > &Vout, PivotVector< Symmetry, Scalar > &Aout)
vector< PivotOverlap1< Symmetry, Scalar > > Env
void prepSweep(const Mps< Symmetry, Scalar > &Vin, Mps< Symmetry, Scalar > &Vout)
void build_LR(const vector< Mps< Symmetry, Scalar > > &Vin, Mps< Symmetry, Scalar > &Vout)
vector< qarray< Nq > > locBasis(size_t loc) const
Tripod< Symmetry, Matrix< Scalar, Dynamic, Dynamic > > get_boundaryTensor(DMRG::DIRECTION::OPTION DIR, size_t usePower=1ul) const
size_t calc_Nqmax() const
MpsBoundaries< Symmetry, Scalar > Boundaries
vector< qarray< Nq > > QoutBot
void innerResize(size_t Mmax)
vector< qarray< Nq > > QoutTop
double squaredNorm() const
Qbasis< Symmetry > inBasis(size_t loc) const
vector< qarray< Nq > > Qmultitarget() const
void sweepStep2(DMRG::DIRECTION::OPTION DIR, size_t loc, const vector< Biped< Symmetry, MatrixType > > &Apair, bool SEPARATE_SV=false)
Qbasis< Symmetry > outBasis(size_t loc) const
vector< vector< Biped< Symmetry, MatrixType > > > A
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={})
std::array< qarray< Nq >, 3 > qarray3
static constexpr int Qinit
vector< vector< std::array< size_t, 12 > > > qrhs
vector< std::array< size_t, 2 > > qlhs
vector< vector< Scalar > > factor_cgcs
vector< PivotMatrix2Terms< Symmetry, Scalar, MpoScalar > > Terms
void outerResize(const PivotVector &Vrhs)
vector< Biped< Symmetry, Matrix< Scalar_, Dynamic, Dynamic > > > data