VMPS++
Loading...
Searching...
No Matches
DmrgIndexGymnastics.h
Go to the documentation of this file.
1#ifndef STRAWBERRY_DMRGINDEXGYMNASTICS
2#define STRAWBERRY_DMRGINDEXGYMNASTICS
3
5#include <tuple>
7
8//include "symmetry/qarray.h"
9#include "DmrgTypedefs.h"
10#include "tensors/Biped.h"
11#include "tensors/Multipede.h"
12#include "numeric_limits.h" // from HELPERS
13
32template<typename Symmetry, typename MatrixType, typename MatrixType2>
33bool LAWA (const qarray<Symmetry::Nq> &Lin, const qarray<Symmetry::Nq> &Lout, const qarray<Symmetry::Nq> &Lmid,
34 const qarray<Symmetry::Nq> &qloc1, const qarray<Symmetry::Nq> &qloc2,
35 const qarray<Symmetry::Nq> &qOp,
39 vector<tuple<qarray3<Symmetry::Nq>,size_t,size_t,size_t> > &result)
40{
41 bool out = false;
42 result.clear();
43
44 auto Routs = Symmetry::reduceSilent(Lin,qloc1);
45 for (const auto &Rout:Routs)
46 {
47 qarray2<Symmetry::Nq> cmp1 = {Lin, Rout};
48 auto qAbra = Abra.dict.find(cmp1);
49 if (qAbra != Abra.dict.end())
50 {
51 auto Rins = Symmetry::reduceSilent(Lout,qloc2);
52 for (const auto &Rin:Rins)
53 {
54 qarray2<Symmetry::Nq> cmp2 = {Lout, Rin};
55 auto qAket = Aket.dict.find(cmp2);
56 if (qAket != Aket.dict.end())
57 {
58 auto Rmids = Symmetry::reduceSilent(Lmid,qOp);
59 for (const auto &Rmid:Rmids)
60 {
61 qarray2<Symmetry::Nq> cmp3 = {Lmid,Rmid};
62 auto qW = W.dict.find(cmp3);
63 if (qW != W.dict.end())
64 {
65 if (Symmetry::validate(qarray3<Symmetry::Nq>{Rin,Rmid,Rout}))
66 {
67 result.push_back(make_tuple(qarray3<Symmetry::Nq>{Rin,Rout,Rmid}, qAbra->second, qAket->second, qW->second));
68 out = true;
69 }
70 }
71 }
72 }
73 }
74 }
75 }
76 return out;
77}
78
79template<typename Symmetry, typename MatrixType, typename MatrixType2>
80bool AWAR (const qarray<Symmetry::Nq> &Rin, const qarray<Symmetry::Nq> &Rout, const qarray<Symmetry::Nq> &Rmid,
81 const qarray<Symmetry::Nq> &qloc1, const qarray<Symmetry::Nq> &qloc2,
82 const qarray<Symmetry::Nq> &qOp,
86 vector<tuple<qarray3<Symmetry::Nq>,size_t,size_t,size_t> > &result)
87{
88 bool out = false;
89 result.clear();
90
91 auto Lins = Symmetry::reduceSilent(Rout,Symmetry::flip(qloc1));
92 for (const auto& Lin : Lins)
93 {
94 qarray2<Symmetry::Nq> cmp1 = {Lin, Rout};
95 auto qAbra = Abra.dict.find(cmp1);
96 if (qAbra != Abra.dict.end())
97 {
98 auto Louts = Symmetry::reduceSilent(Rin,Symmetry::flip(qloc2));
99 for (const auto &Lout : Louts)
100 {
101 qarray2<Symmetry::Nq> cmp2 = {Lout, Rin};
102 auto qAket = Aket.dict.find(cmp2);
103 if (qAket != Aket.dict.end())
104 {
105 auto Lmids = Symmetry::reduceSilent(Rmid,Symmetry::flip(qOp));
106 for (const auto &Lmid : Lmids)
107 {
108 qarray2<Symmetry::Nq> cmp3 = {Lmid,Rmid};
109 auto qW = W.dict.find(cmp3);
110 if (qW != W.dict.end())
111 {
112 if (Symmetry::validate(qarray3<Symmetry::Nq>{Lout,Lmid,Lin}))
113 {
114 result.push_back(make_tuple(qarray3<Symmetry::Nq>{Lin,Lout,Lmid}, qAbra->second, qAket->second, qW->second));
115 out = true;
116 }
117 }
118 }
119 }
120 }
121 }
122 }
123 return out;
124}
125
126template<typename Symmetry, typename MatrixType>
129 size_t s,
130 vector<qarray<Symmetry::Nq> > qloc,
131 const vector<Biped<Symmetry,MatrixType> > &Abra,
132 const vector<Biped<Symmetry,MatrixType> > &Aket,
133 vector<tuple<qarray2<Symmetry::Nq>,size_t,size_t> > &result)
134{
135 bool out = false;
136 result.clear();
137
138 assert(Lin == Lout);
139 qarray<Symmetry::Nq> Linout = Lin; // Lin = Lout = Linout;
140
141 auto Rinouts = Symmetry::reduceSilent(Linout,qloc[s]);
142
143 for (const auto &Rinout : Rinouts)
144 {
145 qarray2<Symmetry::Nq> cmp = {Linout, Rinout};
146 auto qAket = Aket[s].dict.find(cmp);
147
148 if (qAket != Aket[s].dict.end())
149 {
150 auto qAbra = Abra[s].dict.find(cmp);
151
152 if (qAbra != Abra[s].dict.end())
153 {
154 result.push_back(make_tuple(qarray2<Symmetry::Nq>{Rinout,Rinout}, qAbra->second, qAket->second));
155 out = true;
156 }
157 }
158 }
159 return out;
160}
161
162template<typename Symmetry, typename MatrixType>
165 size_t s,
166 vector<qarray<Symmetry::Nq> > qloc,
167 const vector<Biped<Symmetry,MatrixType> > &Abra,
168 const vector<Biped<Symmetry,MatrixType> > &Aket,
169 vector<tuple<qarray2<Symmetry::Nq>,size_t,size_t> > &result)
170{
171 bool out = false;
172 result.clear();
173
174 assert(Rin == Rout);
175 qarray<Symmetry::Nq> Rinout = Rin; // Rin = Rout = Rinout;
176
177 auto Linouts = Symmetry::reduceSilent(Rinout, Symmetry::flip(qloc[s]));
178
179 for (const auto &Linout : Linouts)
180 {
181 qarray2<Symmetry::Nq> cmp = {Linout, Rinout};
182 auto qAket = Aket[s].dict.find(cmp);
183
184 if (qAket != Aket[s].dict.end())
185 {
186 auto qAbra = Abra[s].dict.find(cmp);
187
188 if (qAbra != Abra[s].dict.end())
189 {
190 result.push_back(make_tuple(qarray2<Symmetry::Nq>{Linout,Linout}, qAbra->second, qAket->second));
191 out = true;
192 }
193 }
194 }
195 return out;
196}
197
198template<typename Symmetry, typename MatrixType, typename MpoMatrixType>
200 const qarray<Symmetry::Nq> &Lout,
201 const qarray<Symmetry::Nq> &Lmid,
202 const qarray<Symmetry::Nq> &qOp12,
203 const qarray<Symmetry::Nq> &qOp34,
204 const qarray<Symmetry::Nq> &qmerge13,
205 const qarray<Symmetry::Nq> &qmerge24,
206 const Biped<Symmetry,MatrixType> &AA13,
207 const Biped<Symmetry,MatrixType> &AA24,
210 vector<tuple<qarray3<Symmetry::Nq>,qarray<Symmetry::Nq>,size_t,size_t, size_t, size_t> > &result)
211{
212 bool out = false;
213 result.clear();
214
215 auto qRouts = Symmetry::reduceSilent(Lin, qmerge13);
216 auto qRins = Symmetry::reduceSilent(Lout, qmerge24);
217
218 auto qWs = Symmetry::reduceSilent(Lmid, qOp12);
219
220 for (const auto &qRout:qRouts)
221 {
222 qarray2<Symmetry::Nq> cmp1 = {Lin, qRout};
223 auto q13 = AA13.dict.find(cmp1);
224
225 if (q13 != AA13.dict.end())
226 {
227 for (const auto &qRin:qRins)
228 {
229 qarray2<Symmetry::Nq> cmp2 = {Lout, qRin};
230 auto q24 = AA24.dict.find(cmp2);
231
232 if (q24 != AA24.dict.end())
233 {
234 for (const auto &qW:qWs)
235 {
236 qarray2<Symmetry::Nq> cmp3 = {Lmid,qW};
237 auto qW12 = W12.dict.find(cmp3);
238 if(qW12 != W12.dict.end())
239 {
240 auto qRmids = Symmetry::reduceSilent(qW, qOp34);
241
242 for (const auto &qRmid:qRmids)
243 {
244 qarray2<Symmetry::Nq> cmp4 = {qW,qRmid};
245 auto qW34 = W34.dict.find(cmp4);
246 if(qW34 != W34.dict.end())
247 {
248 if (Symmetry::validate(qarray3<Symmetry::Nq>{qRin,qRmid,qRout}))
249 {
250 result.push_back(make_tuple(qarray3<Symmetry::Nq>{qRin,qRout,qRmid}, qW, q13->second, q24->second, qW12->second, qW34->second));
251 out = true;
252 }
253 }
254 }
255 }
256 }
257 }
258 }
259 }
260 }
261 return out;
262}
263
264template<typename Symmetry, typename Scalar>
265vector<qarray<Symmetry::Nq> > calc_qsplit (const vector<Biped<Symmetry,Eigen::Matrix<Scalar,Dynamic,Dynamic> > > &A1,
266 const vector<qarray<Symmetry::Nq> > &qloc1,
267 const vector<Biped<Symmetry,Eigen::Matrix<Scalar,Dynamic,Dynamic> > > &A2,
268 vector<qarray<Symmetry::Nq> > qloc2,
269 const qarray<Symmetry::Nq> &Qtop,
270 const qarray<Symmetry::Nq> &Qbot)
271{
272 set<qarray<Symmetry::Nq> > qmid_fromL;
273 set<qarray<Symmetry::Nq> > qmid_fromR;
274 vector<qarray<Symmetry::Nq> > A1in;
275 vector<qarray<Symmetry::Nq> > A2out;
276
277 // gather all qin at the left:
278 for (size_t s1=0; s1<qloc1.size(); ++s1)
279 for (size_t q=0; q<A1[s1].dim; ++q)
280 {
281 A1in.push_back(A1[s1].in[q]);
282 }
283 // gather all qout at the right:
284 for (size_t s2=0; s2<qloc2.size(); ++s2)
285 for (size_t q=0; q<A2[s2].dim; ++q)
286 {
287 A2out.push_back(A2[s2].out[q]);
288 }
289
290 for (size_t s1=0; s1<qloc1.size(); ++s1)
291 {
292 auto qls = Symmetry::reduceSilent(A1in, qloc1[s1]);
293 for (auto const &ql:qls)
294 {
295 if (ql<=Qtop and ql>=Qbot)
296 {
297 qmid_fromL.insert(ql);
298 }
299 }
300 }
301 for (size_t s2=0; s2<qloc2.size(); ++s2)
302 {
303 auto qrs = Symmetry::reduceSilent(A2out, Symmetry::flip(qloc2[s2]));
304 for (auto const &qr:qrs)
305 {
306 if (qr<=Qtop and qr>=Qbot)
307 {
308 qmid_fromR.insert(qr);
309 }
310 }
311 }
312
313 vector<qarray<Symmetry::Nq> > qres;
314// sort(qmid_fromL.begin(), qmid_fromL.end());
315// sort(qmid_fromR.begin(), qmid_fromR.end());
316 // take common elements between left and right:
317 set_intersection(qmid_fromL.begin(), qmid_fromL.end(), qmid_fromR.begin(), qmid_fromR.end(), back_inserter(qres));
318 // erase non-unique elements to be sure:
319 sort(qres.begin(), qres.end());
320 qres.erase(unique(qres.begin(), qres.end()), qres.end());
321
322 return qres;
323}
324
325template<typename Symmetry, typename MatrixType>
327 size_t s1s2, const qarray<Symmetry::Nq> &qmerge12,
328 const vector<Biped<Symmetry,MatrixType> > &AAbra,
329 const vector<Biped<Symmetry,MatrixType> > &AAket,
330 vector<tuple<qarray2<Symmetry::Nq>,size_t,size_t> > &result)
331{
332 bool out = false;
333 result.clear();
334
335 auto qRouts = Symmetry::reduceSilent(Lin, qmerge12);
336
337 for (const auto &qRout:qRouts)
338 {
339 qarray2<Symmetry::Nq> cmp1 = {Lin, qRout};
340 auto qbra = AAbra[s1s2].dict.find(cmp1);
341
342 if (qbra != AAbra[s1s2].dict.end())
343 {
344 auto qRins = Symmetry::reduceSilent(Lout, qmerge12);
345
346 for (const auto &qRin:qRins)
347 {
348 if (Symmetry::validate(qarray2<Symmetry::Nq>{qRin,qRout}))
349 {
350 qarray2<Symmetry::Nq> cmp2 = {Lout, qRin};
351 auto qket = AAket[s1s2].dict.find(cmp2);
352
353 if (qket != AAket[s1s2].dict.end())
354 {
355 result.push_back(make_tuple(qarray2<Symmetry::Nq>{qRin,qRout}, qbra->second, qket->second));
356 out = true;
357 }
358 }
359 }
360 }
361 }
362 return out;
363}
364
386template<typename Symmetry, typename MatrixType, typename MpoMatrixType>
390 const Biped<Symmetry,MatrixType> &Abra,
391 const Biped<Symmetry,MatrixType> &Aket,
393 tuple<qarray4<Symmetry::Nq>,size_t,size_t, size_t, size_t> &result)
394{
395 qarray<Symmetry::Nq> qRout = Lin + qloc1;
396 qarray2<Symmetry::Nq> cmp1 = {Lin, qRout};
397 auto q1 = Abra.dict.find(cmp1);
398
399 if (q1 != Abra.dict.end())
400 {
401 qarray<Symmetry::Nq> qRin = Lout + qloc3;
402 qarray2<Symmetry::Nq> cmp2 = {Lout, qRin};
403 auto q2 = Aket.dict.find(cmp2);
404
405 if (q2 != Aket.dict.end())
406 {
407 qarray<Symmetry::Nq> qRbot = Lbot + qloc1 - qloc2;
408 qarray<Symmetry::Nq> qRtop = Ltop + qloc2 - qloc3;
409 qarray2<Symmetry::Nq> cmp3 = {Lbot,qRbot};
410 auto qWbot = Wbot.dict.find(cmp3);
411 if(qWbot != Wbot.dict.end())
412 {
413 qarray2<Symmetry::Nq> cmp4 = {Ltop,qRtop};
414 auto qWtop = Wtop.dict.find(cmp4);
415 if(qWtop != Wtop.dict.end())
416 {
417 result = make_tuple(qarray4<Symmetry::Nq>{qRin,qRout,qRbot,qRtop}, q1->second, q2->second, qWbot->second, qWtop->second);
418 return true;
419 }
420 }
421 }
422 }
423 return false;
424}
425
426
428template<typename Symmetry, typename Scalar>
429void updateInset (const std::vector<std::array<typename Symmetry::qType,3> > &insetOld,
430 const vector<Biped<Symmetry,Eigen::Matrix<Scalar,Dynamic,Dynamic> > > &Abra,
431 const vector<Biped<Symmetry,Eigen::Matrix<Scalar,Dynamic,Dynamic> > > &Aket,
432 const vector<qarray<Symmetry::Nq> > &qloc,
433 const vector<qarray<Symmetry::Nq> > &qOp,
434 std::vector<std::array<typename Symmetry::qType,3> > &insetNew)
435{
436 std::array<typename Symmetry::qType,3> qCheck;
437 Scalar factor_cgc;
438 std::unordered_set<std::array<typename Symmetry::qType,3> > uniqueControl;
439
440 insetNew.clear();
441 for (size_t s1=0; s1<qloc.size(); ++s1)
442 for (size_t s2=0; s2<qloc.size(); ++s2)
443 for (size_t k=0; k<qOp.size(); ++k)
444 {
445 qCheck = {qloc[s2],qOp[k],qloc[s1]};
446 if(!Symmetry::validate(qCheck)) {continue;}
447 for(const auto & [qIn_old,qOut_old,qMid_old] : insetOld)
448 {
449 auto qRouts = Symmetry::reduceSilent(qOut_old,Symmetry::flip(qloc[s1]));
450 auto qRins = Symmetry::reduceSilent(qIn_old,Symmetry::flip(qloc[s2]));
451 for(const auto& qOut_new : qRouts)
452 for(const auto& qIn_new : qRins)
453 {
454 qarray2<Symmetry::Nq> cmp1 = {qOut_new, qOut_old};
455 qarray2<Symmetry::Nq> cmp2 = {qIn_new, qIn_old};
456
457 auto q1 = Abra[s1].dict.find(cmp1);
458 auto q2 = Aket[s2].dict.find(cmp2);
459
460 if (q1!=Abra[s1].dict.end() and
461 q2!=Aket[s2].dict.end())
462 {
463 // qarray<Symmetry::Nq> new_qin = Aket[s2].in[q2->second]; // A.in
464 // qarray<Symmetry::Nq> new_qout = Abra[s1].in[q1->second]; // A†.out = A.in
465 auto qRmids = Symmetry::reduceSilent(qMid_old,Symmetry::flip(qOp[k]));
466 for(const auto& qMid_new : qRmids)
467 {
468 // qarray3<Symmetry::Nq> quple = {new_qin, new_qout, new_qmid};
469 factor_cgc = Symmetry::coeff_buildR(Aket[s2].out[q2->second],qloc[s2],Aket[s2].in[q2->second],
470 qMid_old,qOp[k],qMid_new,
471 Abra[s1].out[q1->second],qloc[s1],Abra[s1].in[q1->second]);
472 if (std::abs(factor_cgc) < ::mynumeric_limits<Scalar>::epsilon()) { continue; }
473 if( auto it=uniqueControl.find({qIn_new,qOut_new,qMid_new}) == uniqueControl.end() )
474 {
475 uniqueControl.insert({qIn_new,qOut_new,qMid_new});
476 insetNew.push_back({qIn_new,qOut_new,qMid_new});
477 }
478 }
479 }
480 }
481 }
482 }
483}
484
487template<typename Symmetry, typename Scalar, typename MpoMatrixType>
488void precalc_blockStructure (const Tripod<Symmetry,Eigen::Matrix<Scalar,Dynamic,Dynamic> > &L,
489 const vector<Biped<Symmetry,Eigen::Matrix<Scalar,Dynamic,Dynamic> > > &Abra,
490 const vector<vector<vector<Biped<Symmetry,MpoMatrixType> > > > &W,
491 const vector<Biped<Symmetry,Eigen::Matrix<Scalar,Dynamic,Dynamic> > > &Aket,
492 const Tripod<Symmetry,Eigen::Matrix<Scalar,Dynamic,Dynamic> > &R,
493 const vector<qarray<Symmetry::Nq> > &qloc,
494 const vector<qarray<Symmetry::Nq> > &qOp,
495 vector<std::array<size_t,2> > &qlhs,
496 vector<vector<std::array<size_t,6> > > &qrhs,
497 vector<vector<Scalar> > &factor_cgcs)
498{
499// Heff.W = W;
500
501 unordered_map<std::array<size_t,2>, std::pair<vector<std::array<size_t,6> >, vector<Scalar> > > lookup;
502 std::array<typename Symmetry::qType,3> qCheck;
503 Scalar factor_cgc;
504
505 #ifndef DMRG_DONT_USE_OPENMP
506 #ifndef __INTEL_COMPILER
507 #pragma omp parallel for collapse(3)
508 #elif __INTEL_COMPILER
509 #pragma omp parallel for
510 #endif
511 #endif
512 for (size_t s1=0; s1<qloc.size(); ++s1)
513 for (size_t s2=0; s2<qloc.size(); ++s2)
514 for (size_t k=0; k<qOp.size(); ++k)
515 {
516 if (!Symmetry::validate(qarray3<Symmetry::Nq>{qloc[s2],qOp[k],qloc[s1]})) {continue;}
517
518 for (size_t qL=0; qL<L.dim; ++qL)
519 {
520 vector<tuple<qarray3<Symmetry::Nq>,size_t,size_t, size_t> > ix;
521 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);
522
523 if (FOUND_MATCH == true)
524 {
525 for(size_t n=0; n<ix.size(); ++n)
526 {
527// if (Aket[s2].block[get<2>(ix[n])].size() == 0) {continue;}
528
529 auto qR = R.dict.find(get<0>(ix[n]));
530
531 if (qR != R.dict.end())
532 {
533 bool ALL_BLOCKS_ARE_EMPTY = true;
534 auto qW = get<3>(ix[n]);
535
536 for (int r=0; r<W[s1][s2][k].block[qW].outerSize(); ++r)
537 for (typename MpoMatrixType::InnerIterator iW(W[s1][s2][k].block[qW],r); iW; ++iW)
538 {
539 if (L.block[qL][iW.row()][0].size() != 0 and
540 R.block[qR->second][iW.col()][0].size() != 0)
541 {
542 ALL_BLOCKS_ARE_EMPTY = false;
543 }
544 }
545 if (ALL_BLOCKS_ARE_EMPTY == false)
546 {
547 // factor_cgc = (Symmetry::NON_ABELIAN)?
548 // Symmetry::coeff_HPsi(Aket[s2].out[get<2>(ix[n])], qloc[s2], Aket[s2].in[get<2>(ix[n])],
549 // get<0>(ix[n])[2], qOp[k], L.mid(qL),
550 // Abra[s1].out[get<1>(ix[n])], qloc[s1], Abra[s1].in[get<1>(ix[n])])
551 // :1.;
552 factor_cgc = (Symmetry::NON_ABELIAN)?
553 Symmetry::coeff_HPsi(Aket[s2].in[get<2>(ix[n])], qloc[s2], Aket[s2].out[get<2>(ix[n])],
554 L.mid(qL), qOp[k], get<0>(ix[n])[2],
555 Abra[s1].in[get<1>(ix[n])], qloc[s1], Abra[s1].out[get<1>(ix[n])])
556 :1.;
557
558 if (std::abs(factor_cgc) < std::abs(mynumeric_limits<Scalar>::epsilon())) {continue;}
559
560 std::array<size_t,2> key = {s1, get<1>(ix[n])};
561 std::array<size_t,6> val = {s2, get<2>(ix[n]), qL, qR->second, k, qW};
562 #ifndef DMRG_DONT_USE_OPENMP
563 #pragma omp critical
564 #endif
565 {
566 lookup[key].first.push_back(val);
567 lookup[key].second.push_back(factor_cgc);
568 }
569 }
570 }
571 }
572 }
573 }
574 }
575
576 qlhs.clear();
577 qrhs.clear();
578 factor_cgcs.clear();
579
580 qlhs.reserve(lookup.size());
581 qrhs.reserve(lookup.size());
582 factor_cgcs.reserve(lookup.size());
583
584 for (auto it=lookup.begin(); it!=lookup.end(); ++it)
585 {
586 qlhs.push_back(it->first);
587 qrhs.push_back((it->second).first);
588 factor_cgcs.push_back((it->second).second);
589 }
590}
591
593template<typename Symmetry, typename Scalar, typename MpoMatrixType>
594void precalc_blockStructure (const Tripod<Symmetry,Eigen::Matrix<Scalar,Dynamic,Dynamic> > &L,
595 const vector<Biped<Symmetry,Eigen::Matrix<Scalar,Dynamic,Dynamic> > > &Abra,
596 const vector<vector<vector<Biped<Symmetry,MpoMatrixType> > > > &W12,
597 const vector<vector<vector<Biped<Symmetry,MpoMatrixType> > > > &W34,
598 const vector<Biped<Symmetry,Eigen::Matrix<Scalar,Dynamic,Dynamic> > > &Aket,
599 const Tripod<Symmetry,Eigen::Matrix<Scalar,Dynamic,Dynamic> > &R,
600 const vector<qarray<Symmetry::Nq> > &qloc12,
601 const vector<qarray<Symmetry::Nq> > &qloc34,
602 const vector<qarray<Symmetry::Nq> > &qOp12,
603 const vector<qarray<Symmetry::Nq> > &qOp34,
605 vector<std::array<size_t,2> > &qlhs,
606 vector<vector<std::array<size_t,12> > > &qrhs,
607 vector<vector<Scalar> > &factor_cgcs)
608{
609 unordered_map<std::array<size_t,2>,
610 std::pair<vector<std::array<size_t,12> >, vector<Scalar> > > lookup;
611
612// vector<unordered_map<std::array<size_t,2>,
613// std::pair<vector<std::array<size_t,12> >, vector<Scalar> > > > lookups(L.dim);
614//
615// #ifdef DMRG_PRECALCBLOCKTSD_PARALLELIZE
616// #pragma omp parallel for
617// #endif
618 for (size_t qL=0; qL<L.dim; ++qL)
619 for (const auto &tsd:TSD)
620 {
621 vector<tuple<qarray3<Symmetry::Nq>,qarray<Symmetry::Nq>,size_t,size_t, size_t, size_t> > ixs;
622 bool FOUND_MATCH = AAWWAA(L.in(qL), L.out(qL), L.mid(qL),
623 qOp12[tsd.k12], qOp34[tsd.k34],
624 tsd.qmerge13, tsd.qmerge24,
625 Abra[tsd.s1s3], Aket[tsd.s2s4], W12[tsd.s1][tsd.s2][tsd.k12], W34[tsd.s3][tsd.s4][tsd.k34], ixs);
626
627 if (FOUND_MATCH)
628 {
629 for (const auto &ix:ixs)
630 {
631 auto qR = R.dict.find(get<0>(ix));
632 auto qW = get<1>(ix);
633 size_t qA13 = get<2>(ix);
634 size_t qA24 = get<3>(ix);
635 size_t qW12 = get<4>(ix);
636 size_t qW34 = get<5>(ix);
637
638 // multiplication of Op12, Op34 in the auxiliary space
639 Scalar factor_cgc6 = (Symmetry::NON_ABELIAN)?
640 Symmetry::coeff_Apair(L.mid(qL), qOp12[tsd.k12], qW,
641 qOp34[tsd.k34], get<0>(ix)[2], tsd.qOp)
642 :1.;
643 // Symmetry::coeff_Apair(L.mid(qL), qOp34[tsd.k34], qW,
644 // qOp12[tsd.k12], get<0>(ix)[2], tsd.qOp)
645 // :1.;
646 if (abs(factor_cgc6) < abs(mynumeric_limits<Scalar>::epsilon())) {continue;}
647
648 if (qR != R.dict.end())
649 {
650 // standard coefficient for H*Psi with environments
651 // Scalar factor_cgcHPsi = (Symmetry::NON_ABELIAN)?
652 // Symmetry::coeff_HPsi(Aket[tsd.s2s4].out[qA24], tsd.qmerge24, Aket[tsd.s2s4].in[qA24],
653 // R.mid(qR->second), tsd.qOp, L.mid(qL),
654 // Abra[tsd.s1s3].out[qA13], tsd.qmerge13, Abra[tsd.s1s3].in[qA13])
655 // :1.;
656 Scalar factor_cgcHPsi = (Symmetry::NON_ABELIAN)?
657 Symmetry::coeff_HPsi(Aket[tsd.s2s4].in[qA24], tsd.qmerge24, Aket[tsd.s2s4].out[qA24],
658 L.mid(qL), tsd.qOp, R.mid(qR->second),
659 Abra[tsd.s1s3].in[qA13], tsd.qmerge13, Abra[tsd.s1s3].out[qA13])
660 :1.;
661
662 std::array<size_t,2> key = {static_cast<size_t>(tsd.s1s3), qA13};
663 std::array<size_t,12> val = {static_cast<size_t>(tsd.s2s4), qA24, qL, qR->second,
664 tsd.s1, tsd.s2, tsd.k12, qW12, tsd.s3, tsd.s4, tsd.k34, qW34};
665// lookups[qL][key].first.push_back(val);
666// lookups[qL][key].second.push_back(factor_cgc6 * tsd.cgc9 * factor_cgcHPsi);
667 lookup[key].first.push_back(val);
668 lookup[key].second.push_back(factor_cgc6 * tsd.cgc9 * factor_cgcHPsi);
669 }
670 }
671 }
672 }
673
674// for (size_t qL=0; qL<L.dim; ++qL)
675// {
676// for (auto it=lookups[qL].begin(); it!=lookups[qL].end(); ++it)
677// {
678// lookup[it->first] = it->second;
679// }
680// }
681
682 qlhs.clear();
683 qrhs.clear();
684 factor_cgcs.clear();
685
686 qlhs.reserve(lookup.size());
687 qrhs.reserve(lookup.size());
688 factor_cgcs.reserve(lookup.size());
689
690 for (auto it=lookup.begin(); it!=lookup.end(); ++it)
691 {
692 qlhs.push_back(it->first);
693 qrhs.push_back((it->second).first);
694 factor_cgcs.push_back((it->second).second);
695 }
696}
697
699template<typename Symmetry, typename Scalar, typename MpoMatrixType>
700void precalc_blockStructure (const Tripod<Symmetry,Eigen::Matrix<Scalar,Dynamic,Dynamic> > &L,
701 const vector<Biped<Symmetry,Eigen::Matrix<Scalar,Dynamic,Dynamic> > > &Abra,
702 const vector<vector<vector<Biped<Symmetry,MpoMatrixType> > > > &W12,
703 const vector<vector<vector<Biped<Symmetry,MpoMatrixType> > > > &W34,
704 const vector<Biped<Symmetry,Eigen::Matrix<Scalar,Dynamic,Dynamic> > > &Aket,
705 const Tripod<Symmetry,Eigen::Matrix<Scalar,Dynamic,Dynamic> > &R,
706 const vector<qarray<Symmetry::Nq> > &qloc12,
707 const vector<qarray<Symmetry::Nq> > &qloc34,
708 const vector<qarray<Symmetry::Nq> > &qOp12,
709 const vector<qarray<Symmetry::Nq> > &qOp34,
710 vector<std::array<size_t,2> > &qlhs,
711 vector<vector<std::array<size_t,12> > > &qrhs,
712 vector<vector<Scalar> > &factor_cgcs)
713{
714 unordered_map<std::array<size_t,2>,
715 std::pair<vector<std::array<size_t,12> >, vector<Scalar> > > lookup;
716
717 Qbasis<Symmetry> loc12; loc12.pullData(qloc12);
718 Qbasis<Symmetry> loc34; loc34.pullData(qloc34);
719 Qbasis<Symmetry> tensor_basis = loc12.combine(loc34);
720 // auto tensor_basis = Symmetry::tensorProd(qloc12, qloc34);
721
722 for (size_t s1=0; s1<qloc12.size(); ++s1)
723 for (size_t s2=0; s2<qloc12.size(); ++s2)
724 for (size_t k12=0; k12<qOp12.size(); ++k12)
725 {
726 if (!Symmetry::validate(qarray3<Symmetry::Nq>{qloc12[s2], qOp12[k12], qloc12[s1]})) {continue;}
727
728 for (size_t s3=0; s3<qloc34.size(); ++s3)
729 for (size_t s4=0; s4<qloc34.size(); ++s4)
730 for (size_t k34=0; k34<qOp34.size(); ++k34)
731 {
732 if (!Symmetry::validate(qarray3<Symmetry::Nq>{qloc34[s4], qOp34[k34], qloc34[s3]})) {continue;}
733
734// vector<qarray<Symmetry::Nq> > qOps;
735// if constexpr (Symmetry::NON_ABELIAN)
736// {
737// if (qOp12[k12] == qOp34[k34])
738// {
739// qOps.push_back(Symmetry::qvacuum());
740// }
741// else
742// {
743// qOps.push_back({3});
744// }
745// }
746// else
747// {
748// qOps = Symmetry::reduceSilent(qOp12[k12], qOp34[k34]);
749// }
750 auto qOps = Symmetry::reduceSilent(qOp12[k12], qOp34[k34]);
751
752 for (const auto &qOp:qOps)
753 {
754// if (find(qOp34.begin(), qOp34.end(), qOp) == qOp34.end()) {continue;}
755
756 auto qmerges13 = Symmetry::reduceSilent(qloc12[s1], qloc34[s3]);
757 auto qmerges24 = Symmetry::reduceSilent(qloc12[s2], qloc34[s4]);
758
759 for (const auto &qmerge13:qmerges13)
760 for (const auto &qmerge24:qmerges24)
761 {
762 // auto qtensor13 = make_tuple(qloc12[s1], s1, qloc34[s3], s3, qmerge13);
763 // auto s1s3 = distance(tensor_basis.begin(), find(tensor_basis.begin(), tensor_basis.end(), qtensor13));
764 // size_t s1s3 = tensor_basis.outer_num(qmerge13) + tensor_basis.leftAmount(qmerge13,{qloc12[s1],qloc34[s3]}) + loc12.inner_num(s1) + loc34.inner_num(s3)*loc12.inner_dim(qloc12[s1]);
765 size_t s1s3 = tensor_basis.outer_num(qmerge13) + tensor_basis.leftOffset(qmerge13,{qloc12[s1],qloc34[s3]},{loc12.inner_num(s1),loc34.inner_num(s3)});
766 // auto qtensor24 = make_tuple(qloc12[s2], s2, qloc34[s4], s4, qmerge24);
767 // auto s2s4 = distance(tensor_basis.begin(), find(tensor_basis.begin(), tensor_basis.end(), qtensor24));
768 // size_t s2s4 = tensor_basis.outer_num(qmerge24) + tensor_basis.leftAmount(qmerge24,{qloc12[s2],qloc34[s4]}) + loc12.inner_num(s2) + loc34.inner_num(s4)*loc12.inner_dim(qloc12[s2]);
769 size_t s2s4 = tensor_basis.outer_num(qmerge24) + tensor_basis.leftOffset(qmerge24,{qloc12[s2],qloc34[s4]},{loc12.inner_num(s2),loc34.inner_num(s4)});
770// cout << "tensor_basis.outer_num=" << tensor_basis.outer_num(qmerge24) << endl;
771// cout << "tensor_basis.leftOffset=" << tensor_basis.leftOffset(qmerge24,{qloc12[s2],qloc34[s4]},{loc12.inner_num(s2),loc34.inner_num(s4)}) << endl;
772// if (tensor_basis.outer_num(qmerge24) == 15) assert(1==-1);
773
774 // tensor product of the MPO operators in the physical space
775 Scalar factor_cgc9 = (Symmetry::NON_ABELIAN)?
776 Symmetry::coeff_tensorProd(qloc12[s2], qloc34[s4], qmerge24,
777 qOp12[k12], qOp34[k34], qOp,
778 qloc12[s1], qloc34[s3], qmerge13)
779 :1.;
780 if (abs(factor_cgc9) < abs(mynumeric_limits<Scalar>::epsilon())) {continue;}
781
782 for (size_t qL=0; qL<L.dim; ++qL)
783 {
784// cout << "qL=" << qL << ", k12=" << k12 << ", k34=" << k34 << ", s1s3=" << s1s3 << ", s2s4=" << s2s4 << endl;
785 vector<tuple<qarray3<Symmetry::Nq>,qarray<Symmetry::Nq>,size_t,size_t, size_t, size_t> > ixs;
786 bool FOUND_MATCH = AAWWAA(L.in(qL), L.out(qL), L.mid(qL),
787 qOp12[k12], qOp34[k34],
788 qmerge13, qmerge24,
789 Abra[s1s3], Aket[s2s4], W12[s1][s2][k12], W34[s3][s4][k34], ixs);
790
791 if (FOUND_MATCH)
792 {
793 for (const auto &ix:ixs)
794 {
795 auto qR = R.dict.find(get<0>(ix));
796 auto qW = get<1>(ix);
797 size_t qA13 = get<2>(ix);
798 size_t qA24 = get<3>(ix);
799 size_t qW12 = get<4>(ix);
800 size_t qW34 = get<5>(ix);
801
802 // multiplication of Op12, Op34 in the auxiliary space
803 Scalar factor_cgc6 = (Symmetry::NON_ABELIAN)?
804 Symmetry::coeff_Apair(L.mid(qL), qOp12[k12], qW,
805 qOp34[k34], get<0>(ix)[2], qOp)
806 :1.;
807 // Scalar factor_cgc6 = (Symmetry::NON_ABELIAN)?
808 // Symmetry::coeff_Apair(get<0>(ix)[2], qOp34[k34], qW,
809 // qOp12[k12] , L.mid(qL) , qOp)
810 // :1.;
811
812 if (abs(factor_cgc6) < abs(mynumeric_limits<Scalar>::epsilon())) {continue;}
813
814 if (qR != R.dict.end())
815 {
816 // standard coefficient for H*Psi with environments
817 // Scalar factor_cgcHPsi = (Symmetry::NON_ABELIAN)?
818 // Symmetry::coeff_HPsi(Aket[s2s4].out[qA24], qmerge24, Aket[s2s4].in[qA24],
819 // R.mid(qR->second), qOp, L.mid(qL),
820 // Abra[s1s3].out[qA13], qmerge13, Abra[s1s3].in[qA13])
821 // :1.;
822 Scalar factor_cgcHPsi = (Symmetry::NON_ABELIAN)?
823 Symmetry::coeff_HPsi(Aket[s2s4].in[qA24], qmerge24, Aket[s2s4].out[qA24],
824 L.mid(qL), qOp, R.mid(qR->second),
825 Abra[s1s3].in[qA13], qmerge13, Abra[s1s3].out[qA13])
826 :1.;
827
828 std::array<size_t,2> key = {static_cast<size_t>(s1s3), qA13};
829 std::array<size_t,12> val = {static_cast<size_t>(s2s4), qA24, qL, qR->second,
830 s1, s2, k12, qW12, s3, s4, k34, qW34};
831 lookup[key].first.push_back(val);
832 lookup[key].second.push_back(factor_cgc6 * factor_cgc9 * factor_cgcHPsi);
833 }
834 }
835 }
836 }
837 }
838 }
839 }
840 }
841
842 qlhs.clear();
843 qrhs.clear();
844 factor_cgcs.clear();
845
846 qlhs.reserve(lookup.size());
847 qrhs.reserve(lookup.size());
848 factor_cgcs.reserve(lookup.size());
849
850 for (auto it=lookup.begin(); it!=lookup.end(); ++it)
851 {
852 qlhs.push_back(it->first);
853 qrhs.push_back((it->second).first);
854 factor_cgcs.push_back((it->second).second);
855 }
856}
857
858#endif
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 AAWWAA(const qarray< Symmetry::Nq > &Lin, const qarray< Symmetry::Nq > &Lout, const qarray< Symmetry::Nq > &Lmid, const qarray< Symmetry::Nq > &qOp12, const qarray< Symmetry::Nq > &qOp34, const qarray< Symmetry::Nq > &qmerge13, const qarray< Symmetry::Nq > &qmerge24, const Biped< Symmetry, MatrixType > &AA13, const Biped< Symmetry, MatrixType > &AA24, const Biped< Symmetry, MpoMatrixType > &W12, const Biped< Symmetry, MpoMatrixType > &W34, vector< tuple< qarray3< Symmetry::Nq >, qarray< 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 AAAA(qarray< Symmetry::Nq > Lin, qarray< Symmetry::Nq > Lout, size_t s1s2, const qarray< Symmetry::Nq > &qmerge12, const vector< Biped< Symmetry, MatrixType > > &AAbra, const vector< Biped< Symmetry, MatrixType > > &AAket, vector< tuple< qarray2< Symmetry::Nq >, size_t, size_t > > &result)
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)
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)
void updateInset(const std::vector< std::array< typename Symmetry::qType, 3 > > &insetOld, const vector< Biped< Symmetry, Eigen::Matrix< Scalar, Dynamic, Dynamic > > > &Abra, const vector< Biped< Symmetry, Eigen::Matrix< Scalar, Dynamic, Dynamic > > > &Aket, const vector< qarray< Symmetry::Nq > > &qloc, const vector< qarray< Symmetry::Nq > > &qOp, std::vector< std::array< typename Symmetry::qType, 3 > > &insetNew)
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)
Definition: Qbasis.h:39
Eigen::Index inner_num(const Eigen::Index &outer_num) const
Definition: Qbasis.h:335
Qbasis< Symmetry > combine(const Qbasis< Symmetry > &other, bool FLIP=false) const
Definition: Qbasis.h:686
Eigen::Index leftOffset(const qType &qnew, const std::array< qType, 2 > &qold, const std::array< Eigen::Index, 2 > &plain_old) const
Definition: Qbasis.h:440
void pullData(const vector< Biped< Symmetry, MatrixType > > &A, const Eigen::Index &leg)
Definition: Qbasis.h:486
Eigen::Index outer_num(const qType &q) const
Definition: Qbasis.h:378
std::array< qarray< Nq >, 2 > qarray2
Definition: qarray.h:51
std::array< qarray< Nq >, 3 > qarray3
Definition: qarray.h:52
std::array< qarray< Nq >, 4 > qarray4
Definition: qarray.h:53
Definition: Biped.h:64
std::unordered_map< std::array< qType, 2 >, std::size_t > dict
Definition: Biped.h:104
Definition: qarray.h:26