VMPS++
Loading...
Searching...
No Matches
DmrgHamiltonianTerms.h
Go to the documentation of this file.
1#ifndef DMRG_HAMILTONIAN_TERMS
2#define DMRG_HAMILTONIAN_TERMS
3
5#include <vector>
6#include <string>
8
9#include "SuperMatrix.h"
10#include "numeric_limits.h" // from TOOLS
12#include "symmetry/qarray.h"
13
14template<typename Symmetry, typename Scalar> class HamiltonianTerms
15{
16private:
18 typename Symmetry::qType qvac = Symmetry::qvacuum();
19 typedef Eigen::Matrix<Scalar, Eigen::Dynamic, Eigen::Dynamic> MatrixType;
20
25 std::vector<OperatorType> local;
26
31 std::vector<bool> localSet;
32
37 std::vector<int> hilbert_dimension;
38
42 std::size_t N_sites;
43
48 std::vector<std::vector<std::string>> info;
49
53 std::string label="";
54
58 bool OPEN_BC;
59
64 std::vector<std::vector<std::vector<std::vector<OperatorType>>>> outgoing;
65
70 std::vector<std::vector<std::vector<std::vector<OperatorType>>>> incoming;
71
76 std::vector<std::vector<std::vector<std::vector<OperatorType>>>> transfer;
77
82 std::vector<std::vector<std::vector<MatrixType>>> coupling;
83
87 std::size_t n_max = 0;
88
94 void assert_hilbert(std::size_t loc, int dim);
95
99 void compress(std::vector<std::vector<std::vector<std::vector<OperatorType>>>> &incoming_compressed, std::vector<std::vector<std::vector<std::vector<OperatorType>>>> &outgoing_compressed);
100
101public:
102
107
113 HamiltonianTerms(std::size_t L, bool bc = true);
114
124 void push(std::size_t n, std::size_t loc, Scalar lambda, OperatorType outOp, std::vector<OperatorType> trans, OperatorType inOp);
125
134 void push_local(std::size_t loc, Scalar lambda, OperatorType Op);
135
145 void push_tight(std::size_t loc, Scalar lambda, OperatorType Op1, OperatorType Op2);
146
157 void push_nextn(std::size_t loc, Scalar lambda, OperatorType Op1, OperatorType Trans, OperatorType Op2);
158
163 void save_label(std::size_t loc, const std::string &label);
164
168 void set_name(const std::string &label_in) {label = label_in;}
169
173 std::vector<std::string> get_info() const;
174
179 std::size_t Hilbert_dimension(std::size_t loc) const;
180
186 std::vector<SuperMatrix<Symmetry,Scalar>> construct_Matrix();
187
191 std::string name() const {return label;}
192
193
199 void scale(double factor, double offset=0.);
200
204 std::size_t size() const {return N_sites;}
205
209 template<typename OtherScalar> HamiltonianTerms<Symmetry, OtherScalar> cast();
210
214 OperatorType const& localOps(std::size_t loc) const {return local[loc];}
215
219 std::vector<std::vector<OperatorType>> const& inOps(std::size_t n, std::size_t loc) const {assert(n > 1 and "Only possible for interactions with ranges > 1"); return incoming[n-1][loc];}
220
224 std::vector<std::vector<OperatorType>> const& outOps(std::size_t n, std::size_t loc) const {assert(n > 1 and "Only possible for interactions with ranges > 1"); return outgoing[n-1][loc];}
225
229 std::vector<std::vector<OperatorType>> const& transferOps(std::size_t n, std::size_t loc) const {assert(n > 1 and "Only possible for interactions with ranges > 1"); return transfer[n-1][loc];}
230
234 std::vector<OperatorType> const& tight_inOps(std::size_t loc) const {return incoming[0][loc][0];}
235
239 std::vector<OperatorType> const& tight_outOps(std::size_t loc) const {return outgoing[0][loc][0];}
240
244 std::vector<std::vector<OperatorType>> const& nextn_inOps(std::size_t loc) const {return incoming[1][loc];}
245
249 std::vector<std::vector<OperatorType>> const& nextn_outOps(std::size_t loc) const {return outgoing[1][loc];}
250};
251
252template<typename Symmetry, typename Scalar> void HamiltonianTerms<Symmetry, Scalar>::assert_hilbert(std::size_t loc, int dim)
253{
254 if(hilbert_dimension[loc] == 0)
255 {
256 hilbert_dimension[loc] = dim;
257 }
258 else
259 {
260 assert(hilbert_dimension[loc] == dim and "Dimensions of operator and local Hilbert space do not match!");
261 }
262}
263
264template<typename Symmetry, typename Scalar> void HamiltonianTerms<Symmetry,Scalar>::
265push(std::size_t n, std::size_t loc, Scalar lambda, OperatorType outOp, std::vector<OperatorType> transOps, OperatorType inOp)
266{
267 assert(loc < N_sites and "Chosen lattice site out of bounds");
268 if(lambda != 0.)
269 {
270 if(n == 0)
271 {
272 //std::cout << "Local interaction at site " << loc << std::endl;
273 assert(outOp.Q == qvac and "Local operator is not a singlet");
274 assert_hilbert(loc, outOp.data.rows());
275 if(localSet[loc])
276 {
277 local[loc] += lambda * outOp;
278 }
279 else
280 {
281 local[loc] = lambda * outOp;
282 localSet[loc] = true;
283 }
284 }
285 else
286 {
287 //std::cout << n << ".-neighbour interaction between the sites " << loc << " and " << (loc+n)%N_sites << std::endl;
288 assert(transOps.size() == n-1 and "Distance does not match to number of transfer operators!");
289 if(n > n_max)
290 {
291 for(int i=n_max; i<n; ++i)
292 {
293 std::vector<std::vector<MatrixType>> temp_coup(N_sites);
294 coupling.push_back(temp_coup);
295 std::vector<std::vector<std::vector<OperatorType>>> temp_ops(N_sites);
296 outgoing.push_back(temp_ops);
297 incoming.push_back(temp_ops);
298 transfer.push_back(temp_ops);
299 }
300 n_max = n;
301 }
302
303 std::ptrdiff_t transptr;
304 if(n == 1)
305 {
306 transptr = 0;
307 if(coupling[0][loc].size() == 0)
308 {
309 Eigen::Matrix<Scalar, Eigen::Dynamic, Eigen::Dynamic> matrix = Eigen::Matrix<Scalar, Eigen::Dynamic, Eigen::Dynamic>::Zero(1,1);
310 std::vector<OperatorType> temp;
311
312 coupling[0][loc].push_back(matrix);
313 outgoing[0][loc].push_back(temp);
314 incoming[0][(loc+1)%N_sites].push_back(temp);
315 }
316 }
317 else
318 {
319 transptr = std::distance(transfer[n-1][loc].begin(), find(transfer[n-1][loc].begin(), transfer[n-1][loc].end(), transOps));
320 if(transptr >= transfer[n-1][loc].size()) // If the operator cannot be found, push it to the corresponding terms and resize the interaction matrix
321 {
322 transfer[n-1][loc].push_back(transOps);
323 for(std::size_t t=0; t<n-1; ++t)
324 {
325 assert_hilbert((loc+t+1)%N_sites, transOps[t].data.rows());
326 }
327
328 Eigen::Matrix<Scalar, Eigen::Dynamic, Eigen::Dynamic> matrix = Eigen::Matrix<Scalar, Eigen::Dynamic, Eigen::Dynamic>::Zero(1,1);
329 std::vector<OperatorType> temp;
330
331 coupling[n-1][loc].push_back(matrix);
332 outgoing[n-1][loc].push_back(temp);
333 incoming[n-1][(loc+n)%N_sites].push_back(temp);
334 }
335 }
336
337 std::ptrdiff_t outptr = std::distance(outgoing[n-1][loc][transptr].begin(), find(outgoing[n-1][loc][transptr].begin(), outgoing[n-1][loc][transptr].end(), outOp));
338 if(outptr >= outgoing[n-1][loc][transptr].size())
339 {
340 assert_hilbert(loc, outOp.data.rows());
341 outgoing[n-1][loc][transptr].push_back(outOp);
342 coupling[n-1][loc][transptr].conservativeResize(outgoing[n-1][loc][transptr].size(), incoming[n-1][(loc+n)%N_sites][transptr].size());
343 coupling[n-1][loc][transptr].bottomRows(1).setZero();
344 hilbert_dimension[loc] = outOp.data.rows();
345 //std::cout << "Outgoing operator for " << n << ".-neighbour interaction between the sites " << loc << " and " << (loc+n)%N_sites << " was not found, so a new row is added to the coupling matrix and a " << outOp.Q << "-operator is pushed" << std::endl;
346 }
347 std::ptrdiff_t inptr = std::distance(incoming[n-1][(loc+n)%N_sites][transptr].begin(), find(incoming[n-1][(loc+n)%N_sites][transptr].begin(), incoming[n-1][(loc+n)%N_sites][transptr].end(), inOp));
348 if(inptr >= incoming[n-1][(loc+n)%N_sites][transptr].size())
349 {
350 assert_hilbert((loc+n)%N_sites, inOp.data.rows());
351 incoming[n-1][(loc+n)%N_sites][transptr].push_back(inOp);
352 coupling[n-1][loc][transptr].conservativeResize(outgoing[n-1][loc][transptr].size(), incoming[n-1][(loc+n)%N_sites][transptr].size());
353 coupling[n-1][loc][transptr].rightCols(1).setZero();
354 hilbert_dimension[(loc+n)%N_sites] = inOp.data.rows();
355 //std::cout << "Incoming operator for " << n << ".-neighbour interaction between the sites " << loc << " and " << (loc+n)%N_sites << " was not found, so no new column is added to the coupling matrix and a " << inOp.Q << "-operator is pushed" << std::endl;
356
357 }
358 coupling[n-1][loc][transptr](outptr, inptr) += lambda;
359 }
360 }
361}
362
363template<typename Symmetry, typename Scalar> HamiltonianTerms<Symmetry,Scalar>::
364HamiltonianTerms(std::size_t L, bool BC) : N_sites(L)
365{
366 info.resize(N_sites);
367 hilbert_dimension.resize(N_sites, 0);
368 local.resize(N_sites);
369 localSet.resize(N_sites, false);
370 OPEN_BC = BC;
371}
372
373template<typename Symmetry, typename Scalar> void HamiltonianTerms<Symmetry,Scalar>::
374save_label(std::size_t loc, const std::string &label)
375{
376 assert(loc < N_sites and "Chosen lattice site out of bounds");
377 if(label!="")
378 {
379 info[loc].push_back(label);
380 }
381}
382
383template<typename Symmetry, typename Scalar> std::vector<std::string> HamiltonianTerms<Symmetry,Scalar>::
384get_info() const
385{
386 std::vector<std::string> res(N_sites);
387 for(std::size_t loc=0; loc<N_sites; ++loc)
388 {
389 std::stringstream ss;
390 if (info[loc].size()>0)
391 {
392 std::copy(info[loc].begin(), info[loc].end()-1, std::ostream_iterator<std::string>(ss,","));
393 ss << info[loc].back();
394 }
395 else
396 {
397 ss << "no info";
398 }
399
400 res[loc] = ss.str();
401
402 while (res[loc].find("perp") != std::string::npos) res[loc].replace(res[loc].find("perp"), 4, "⟂");
403 while (res[loc].find("para") != std::string::npos) res[loc].replace(res[loc].find("para"), 4, "∥");
404 while (res[loc].find("prime") != std::string::npos) res[loc].replace(res[loc].find("prime"), 5, "'");
405 while (res[loc].find("Perp") != std::string::npos) res[loc].replace(res[loc].find("Perp"), 4, "⟂");
406 while (res[loc].find("Para") != std::string::npos) res[loc].replace(res[loc].find("Para"), 4, "∥");
407 while (res[loc].find("Prime") != std::string::npos) res[loc].replace(res[loc].find("Prime"), 5, "'");
408 while (res[loc].find("mu") != std::string::npos) res[loc].replace(res[loc].find("mu"), 2, "µ");
409 while (res[loc].find("Delta") != std::string::npos) res[loc].replace(res[loc].find("Delta"), 5, "Δ");
410 while (res[loc].find("next") != std::string::npos) res[loc].replace(res[loc].find("next"), 4, "ₙₑₓₜ");
411 while (res[loc].find("prev") != std::string::npos) res[loc].replace(res[loc].find("prev"), 4, "ₚᵣₑᵥ");
412 while (res[loc].find("3site") != std::string::npos) res[loc].replace(res[loc].find("3site"), 5, "₃ₛᵢₜₑ");
413 while (res[loc].find("sub") != std::string::npos) res[loc].replace(res[loc].find("sub"), 3, "ˢᵘᵇ");
414 while (res[loc].find("rung") != std::string::npos) res[loc].replace(res[loc].find("rung"), 4, "ʳᵘⁿᵍ");
415 while (res[loc].find("t0") != std::string::npos) res[loc].replace(res[loc].find("t0"), 2, "t₀");
416
417 //⁰ ¹ ² ³ ⁴ ⁵ ⁶ ⁷ ⁸ ⁹ ⁺ ⁻ ⁼ ⁽ ⁾ ₀ ₁ ₂ ₃ ₄ ₅ ₆ ₇ ₈ ₉ ₊ ₋ ₌ ₍ ₎
418 //ᵃ ᵇ ᶜ ᵈ ᵉ ᶠ ᵍ ʰ ⁱ ʲ ᵏ ˡ ᵐ ⁿ ᵒ ᵖ ʳ ˢ ᵗ ᵘ ᵛ ʷ ˣ ʸ ᶻ
419 //ᴬ ᴮ ᴰ ᴱ ᴳ ᴴ ᴵ ᴶ ᴷ ᴸ ᴹ ᴺ ᴼ ᴾ ᴿ ᵀ ᵁ ⱽ ᵂ
420 //ₐ ₑ ₕ ᵢ ⱼ ₖ ₗ ₘ ₙ ₒ ₚ ᵣ ₛ ₜ ᵤ ᵥ ₓ
421 //ᵅ ᵝ ᵞ ᵟ ᵋ ᶿ ᶥ ᶲ ᵠ ᵡ ᵦ ᵧ ᵨ ᵩ ᵪ
422 }
423 return res;
424}
425
426template<typename Symmetry, typename Scalar> std::size_t HamiltonianTerms<Symmetry,Scalar>::
427Hilbert_dimension(std::size_t loc) const
428{
429 assert(loc < N_sites and "Chosen lattice site out of bounds");
430 return hilbert_dimension[loc];
431}
432
433template<typename Symmetry, typename Scalar> void HamiltonianTerms<Symmetry,Scalar>::
434push_local(std::size_t loc, Scalar lambda, OperatorType Op)
435{
436 push(0, loc, lambda, Op, {}, Op);
437}
438
439template<typename Symmetry, typename Scalar> void HamiltonianTerms<Symmetry,Scalar>::
440push_tight(std::size_t loc, Scalar lambda, OperatorType Op1, OperatorType Op2)
441{
442 push(1, loc, lambda, Op1, {}, Op2);
443}
444
445template<typename Symmetry, typename Scalar> void HamiltonianTerms<Symmetry,Scalar>::
446push_nextn(std::size_t loc, Scalar lambda, OperatorType Op1, OperatorType Trans, OperatorType Op2)
447{
448 push(2, loc, lambda, Op1, {Trans}, Op2);
449}
450
451template<typename Symmetry, typename Scalar> void HamiltonianTerms<Symmetry, Scalar>::
452compress(std::vector<std::vector<std::vector<std::vector<OperatorType>>>> &outgoing_compressed, std::vector<std::vector<std::vector<std::vector<OperatorType>>>> &incoming_compressed)
453{
454 outgoing_compressed.resize(n_max);
455 incoming_compressed.resize(n_max);
456 outgoing_compressed[0].resize(N_sites);
457 incoming_compressed[0].resize(N_sites);
458 for(std::size_t loc=0; loc<N_sites; ++loc)
459 {
460 outgoing_compressed[0][loc].resize(outgoing[0][loc].size());
461 incoming_compressed[0][(loc+1)%N_sites].resize(incoming[0][(loc+1)%N_sites].size());
462 if(outgoing[0][loc].size() > 0)
463 {
464 if(outgoing[0][loc][0].size() < incoming[0][(loc+1)%N_sites][0].size())
465 {
466 //outgoing_compressed[0][loc].push_back(outgoing[0][loc][0]);
467 //incoming_compressed[0][(loc+1)%N_sites].push_back(coupling[0][loc][0] * incoming[0][(loc+1)%N_sites][0]);
468 outgoing_compressed[0][loc][0] = outgoing[0][loc][0];
469 incoming_compressed[0][(loc+1)%N_sites][0] = coupling[0][loc][0] * incoming[0][(loc+1)%N_sites][0];
470 }
471 else
472 {
473 //outgoing_compressed[0][loc].push_back(outgoing[0][loc][0] * coupling[0][loc][0]);
474 //incoming_compressed[0][(loc+1)%N_sites].push_back(incoming[0][(loc+1)%N_sites][0]);
475 outgoing_compressed[0][loc][0] = outgoing[0][loc][0] * coupling[0][loc][0];
476 incoming_compressed[0][(loc+1)%N_sites][0] = incoming[0][(loc+1)%N_sites][0];
477 }
478 }
479 }
480 for(std::size_t n=1; n<n_max; ++n)
481 {
482 outgoing_compressed[n].resize(N_sites);
483 incoming_compressed[n].resize(N_sites);
484 for(std::size_t loc=0; loc<N_sites; ++loc)
485 {
486 outgoing_compressed[n][loc].resize(transfer[n][loc].size());
487 incoming_compressed[n][(loc+n+1)%N_sites].resize(transfer[n][loc].size());
488 for(std::size_t t=0; t<transfer[n][loc].size(); ++t)
489 {
490 if(outgoing[n][loc][t].size() < incoming[n][(loc+n+1)%N_sites][t].size())
491 {
492 outgoing_compressed[n][loc][t] = outgoing[n][loc][t];
493 incoming_compressed[n][(loc+n+1)%N_sites][t] = coupling[n][loc][t] * incoming[n][(loc+n+1)%N_sites][t];
494 }
495 else
496 {
497 outgoing_compressed[n][loc][t] = outgoing[n][loc][t] * coupling[n][loc][t];
498 incoming_compressed[n][(loc+n+1)%N_sites][t] = incoming[n][(loc+n+1)%N_sites][t];
499 }
500 }
501 }
502 }
503}
504
505template<typename Symmetry, typename Scalar> std::vector<SuperMatrix<Symmetry, Scalar>> HamiltonianTerms<Symmetry, Scalar>::
507{
508 std::vector<std::vector<std::vector<std::vector<OperatorType>>>> outgoing_compressed;
509 std::vector<std::vector<std::vector<std::vector<OperatorType>>>> incoming_compressed;
510 compress(outgoing_compressed, incoming_compressed);
511
512 std::vector<SuperMatrix<Symmetry, Scalar>> G;
513 for (std::size_t loc=0; loc<N_sites; ++loc)
514 {
516 if(hilbert_dimension[loc] == 0) // Create a trivial SuperMatrix if no operator has been set.
517 {
518 hilbert_dimension[loc] = 1;
519 OperatorType Id(Matrix<Scalar,Eigen::Dynamic,Eigen::Dynamic>::Identity(hilbert_dimension[loc],hilbert_dimension[loc]).sparseView(),Symmetry::qvacuum());
520 S.set(2,2,hilbert_dimension[loc]);
521 S(0,0) = Id;
522 S(1,1) = Id;
523 //std::cout << "SuperMatrix at site " << loc << " is trivial (no operators have been added there)\n" << std::endl;
524 }
525 else if(n_max == 0)
526 {
527 //std::cout << "Filling the SuperMatrix at site " << loc << ":" << std::endl;
528 OperatorType Id(Matrix<Scalar,Eigen::Dynamic,Eigen::Dynamic>::Identity(hilbert_dimension[loc],hilbert_dimension[loc]).sparseView(),Symmetry::qvacuum());
529 S.set(2,2,hilbert_dimension[loc]);
530 S(0,0) = Id;
531 //std::cout << "\tEntry (0,0): Identity" << std::endl;
532 S(1,0) = local[loc];
533 //std::cout << "\tEntry (1,0): Local term" << std::endl;
534 S(1,1) = Id;
535 //std::cout << "\tEntry (1,1): Identity" << std::endl;
536
537 //std::cout << "SuperMatrix at site " << loc << " has dimension 2x2, dimension of local Hilbert space: " << hilbert_dimension[loc] << "\n" << std::endl;
538 }
539 else
540 {
541 //std::cout << "Filling the SuperMatrix at site " << loc << ":" << std::endl;
542
543 std::size_t rows = 2;
544 std::size_t cols = 2;
545 if(incoming_compressed[0][loc].size() > 0)
546 {
547 rows += incoming_compressed[0][loc][0].size();
548 }
549 if(outgoing_compressed[0][loc].size() > 0)
550 {
551 cols += outgoing_compressed[0][loc][0].size();
552 }
553 for(std::size_t n=1; n<n_max; ++n)
554 {
555 for(std::size_t t=0; t<incoming_compressed[n][loc].size(); ++t)
556 {
557 rows += incoming_compressed[n][loc][t].size();
558 }
559 for(std::size_t t=0; t<outgoing_compressed[n][loc].size(); ++t)
560 {
561 cols += outgoing_compressed[n][loc][t].size();
562 }
563
564 for(std::size_t m=0; m<n; ++m)
565 {
566 for(std::size_t t=0; t<transfer[n][(N_sites+loc-m-1)%N_sites].size(); ++t)
567 {
568 rows += outgoing_compressed[n][(N_sites+loc-m-1)%N_sites][t].size();
569 cols += outgoing_compressed[n][(N_sites+loc-m-1)%N_sites][t].size();
570 }
571 }
572 }
573
574 OperatorType Id(Matrix<Scalar,Eigen::Dynamic,Eigen::Dynamic>::Identity(hilbert_dimension[loc],hilbert_dimension[loc]).sparseView(),Symmetry::qvacuum());
575 S.set(rows, cols, hilbert_dimension[loc]);
576 S(0,0) = Id;
577 //std::cout << "\tEntry (0,0): Identity" << std::endl;
578
579
580 std::size_t current = 1;
581 if(incoming_compressed[0][loc].size() > 0)
582 {
583 for(std::size_t i=0; i<incoming_compressed[0][loc][0].size(); ++i)
584 {
585 //std::cout << "\tEntry (" << current << ",0): Incoming next-neighbour interaction term" << std::endl;
586 S(current++, 0) = incoming_compressed[0][loc][0][i];
587 }
588 }
589
590 for(std::size_t n=1; n<n_max; ++n)
591 {
592 for(std::size_t t=0; t<incoming_compressed[n][loc].size(); ++t)
593 {
594 for(std::size_t i=0; i<incoming_compressed[n][loc][t].size(); ++i)
595 {
596 //std::cout << "\tEntry (" << current << ",0): Incoming " << n+1 << ".-neighbour interaction term" << std::endl;
597 S(current++, 0) = incoming_compressed[n][loc][t][i];
598 }
599 }
600 std::size_t temp = current;
601
602 for(std::size_t m=0; m<n; ++m)
603 {
604 for(std::size_t t=0; t<transfer[n][(N_sites+loc-m-1)%N_sites].size(); ++t)
605 {
606 current += outgoing_compressed[n][(N_sites+loc-m-1)%N_sites][t].size();
607 }
608 }
609 if(temp < current)
610 {
611 //std::cout << "\tEntries (" << temp << ",0)-(" << current-1 << ",0): Skipped due to transfer operators of " << n+1 << ".-neighbour interactions" << std::endl;
612 }
613 }
614
615 if (!localSet[loc]) // If no local interaction has been added, the local interaction becomes a dummy SiteOperator with correct dimension
616 {
617 local[loc] = 0*Id;
618 }
619 S(rows-1,0) = local[loc];
620
621 //std::cout << "\tEntry (" << rows-1 << ",0): Local term" << std::endl;
622
623 current = 1;
624
625 if(outgoing_compressed[0][loc].size() > 0)
626 {
627 for(std::size_t i=0; i<outgoing_compressed[0][loc][0].size(); ++i)
628 {
629 //std::cout << "\tEntry (" << rows-1 << "," << current << "): Outgoing next-neighbour interaction term" << std::endl;
630 S(rows-1, current++) = outgoing_compressed[0][loc][0][i];
631 }
632 }
633
634 for(std::size_t n=1; n<n_max; ++n)
635 {
636 std::size_t temp = current;
637
638 for(std::size_t m=0; m<n; ++m)
639 {
640 for(std::size_t t=0; t<transfer[n][(N_sites+loc-m-1)%N_sites].size(); ++t)
641 {
642 current += outgoing_compressed[n][(N_sites+loc-m-1)%N_sites][t].size();
643 }
644 }
645 if(temp < current)
646 {
647 //std::cout << "\tEntries (" << rows-1 << "," << temp << ")-(" << rows-1 << "," << current-1 << "): Skipped due to transfer operators of " << n+1 << ".-neighbour interactions" << std::endl;
648 }
649 for(std::size_t t=0; t<outgoing_compressed[n][loc].size(); ++t)
650 {
651 for(std::size_t i=0; i<outgoing_compressed[n][loc][t].size(); ++i)
652 {
653 //std::cout << "\tEntry (" << rows-1 << "," << current << "): Outgoing " << n+1 << ".-neighbour interaction term" << std::endl;
654 S(rows-1, current++) = outgoing_compressed[n][loc][t][i];
655 }
656 }
657 }
658
659 S(rows-1,cols-1) = Id;
660 //std::cout << "\tEntry (" << rows-1 << "," << cols-1 << "): Identity" << std::endl;
661
662 std::size_t current_row = 1;
663 std::size_t current_col = 1;
664 if(incoming_compressed[0][loc].size() > 0)
665 {
666 current_row += incoming_compressed[0][loc][0].size();
667
668 }
669 if(outgoing_compressed[0][loc].size() > 0)
670 {
671 current_col += outgoing_compressed[0][loc][0].size();
672 }
673 for(std::size_t n=1; n<n_max; ++n)
674 {
675 for(std::size_t t=0; t<incoming_compressed[n][loc].size(); ++t)
676 {
677 current_row += incoming_compressed[n][loc][t].size();
678 }
679 for(std::size_t m=0; m<n; ++m)
680 {
681 for(std::size_t t=0; t<transfer[n][(N_sites + loc - n + m) % N_sites].size(); ++t)
682 {
683 for(std::size_t i=0; i<outgoing_compressed[n][(N_sites + loc - n + m)%N_sites][t].size(); ++i)
684 {
685 //std::cout << "\tEntry (" << current_row << "," << current_col << "): Transfer operator for a " << n+1 << ".-neighbour interaction ranging from site " << (N_sites + loc - n + m)%N_sites << " to site " << (loc + 1 + m)%N_sites << std::endl;
686 S(current_row++, current_col++) = transfer[n][(N_sites + loc - n + m)%N_sites][t][n-1-m];
687 }
688 }
689 }
690 for(std::size_t t=0; t<outgoing_compressed[n][loc].size(); ++t)
691 {
692 current_col += outgoing_compressed[n][loc][t].size();
693 }
694 }
695
696 //std::cout << "SuperMatrix at site " << loc << " has dimension " << rows << "x" << cols << ", dimension of local Hilbert space: " << hilbert_dimension[loc] << "\n" << std::endl;
697 }
698 if (OPEN_BC and loc==0)
699 {
700 G.push_back(S.row(S.rows()-1));
701 }
702 else if (OPEN_BC and loc==N_sites-1)
703 {
704 G.push_back(S.col(0));
705 }
706 else
707 {
708 G.push_back(S);
709 }
710 }
711 return G;
712}
713
714
715template<typename Symmetry, typename Scalar> void HamiltonianTerms<Symmetry,Scalar>::
716scale (double factor, double offset)
717{
718 if (std::abs(factor-1.) > ::mynumeric_limits<double>::epsilon())
719 {
720 for (std::size_t loc=0; loc<N_sites; ++loc)
721 {
722 local[loc] = factor * local[loc];
723 for(std::size_t n=0; n<n_max; ++n)
724 {
725 for(std::size_t t=0; t<coupling[n][loc].size(); ++t)
726 {
727 coupling[n][loc][t] *= factor;
728 }
729 }
730 }
731 }
732
733 if (std::abs(offset) > ::mynumeric_limits<double>::epsilon())
734 {
735 for(std::size_t loc=0; loc<N_sites; ++loc)
736 {
737 if(hilbert_dimension[loc] > 0)
738 {
740 Id.data = Matrix<Scalar,Dynamic,Dynamic>::Identity(hilbert_dimension[loc],hilbert_dimension[loc]).sparseView();
741 push_local(loc, offset, Id);
742 }
743 }
744 }
745}
746
747template<typename Symmetry, typename Scalar>
748template<typename OtherScalar>
750cast()
751{
752 HamiltonianTerms<Symmetry, OtherScalar> other(N_sites, OPEN_BC);
753 other.set_name(label);
754 for(std::size_t loc=0; loc<N_sites; ++loc)
755 {
756 for(std::size_t i=0; i<info[loc].size(); ++i)
757 {
758 other.save_label(loc, info[loc][i]);
759 }
760 other.push_local(loc, 1., local[loc].template cast<OtherScalar>());
761
762 if(outgoing[0][loc].size() > 0)
763 {
764 Eigen::Matrix<OtherScalar, Eigen::Dynamic, Eigen::Dynamic> other_coupling = coupling[0][loc][0].template cast<OtherScalar>();
765 for(std::size_t i=0; i<other_coupling.rows(); ++i)
766 {
767 for(std::size_t j=0; j<other_coupling.cols(); ++j)
768 {
769 SiteOperator<Symmetry, OtherScalar> other_out = outgoing[0][loc][0][i].template cast<OtherScalar>();
770 SiteOperator<Symmetry, OtherScalar> other_in = incoming[0][(loc+1)%N_sites][0][j].template cast<OtherScalar>();
771 other.push_tight(loc, other_coupling(i,j), other_out, other_in);
772 }
773 }
774 }
775 for(std::size_t n=1; n<n_max; ++n)
776 {
777 for(std::size_t t=0; t<transfer[n][loc].size(); ++t)
778 {
779 Eigen::Matrix<OtherScalar, Eigen::Dynamic, Eigen::Dynamic> other_coupling = coupling[n][loc][t].template cast<OtherScalar>();
780 for(std::size_t i=0; i<other_coupling.rows(); ++i)
781 {
782 for(std::size_t j=0; j<other_coupling.cols(); ++j)
783 {
784 SiteOperator<Symmetry, OtherScalar> other_out = outgoing[n][loc][t][i].template cast<OtherScalar>();
785 SiteOperator<Symmetry, OtherScalar> other_in = incoming[n][(loc+1+n)%N_sites][t][j].template cast<OtherScalar>();
786 std::vector<SiteOperator<Symmetry, OtherScalar>> other_transfer;
787 for(std::size_t k=0; k<transfer[n][loc][t].size(); ++k)
788 {
789 other_transfer.push_back(transfer[n][loc][t][k].template cast<OtherScalar>());
790 }
791 other.push(n+1, loc, other_coupling(i,j), other_out, other_transfer, other_in);
792 }
793 }
794 }
795 }
796 }
797 return other;
798}
799
800template<typename Symmetry> using HamiltonianTermsXd = HamiltonianTerms<Symmetry,double>;
802
803#endif
size_t dim(const PivotMatrix0< Symmetry, Scalar, MpoScalar > &H)
BC
Definition: DmrgTypedefs.h:161
void set_name(const std::string &label_in)
std::string name() const
void push_tight(std::size_t loc, Scalar lambda, OperatorType Op1, OperatorType Op2)
std::vector< std::vector< OperatorType > > const & inOps(std::size_t n, std::size_t loc) const
std::vector< std::vector< OperatorType > > const & outOps(std::size_t n, std::size_t loc) const
void save_label(std::size_t loc, const std::string &label)
std::vector< std::vector< std::vector< std::vector< OperatorType > > > > incoming
std::vector< std::vector< OperatorType > > const & nextn_inOps(std::size_t loc) const
void push(std::size_t n, std::size_t loc, Scalar lambda, OperatorType outOp, std::vector< OperatorType > trans, OperatorType inOp)
Symmetry::qType qvac
HamiltonianTerms< Symmetry, OtherScalar > cast()
std::vector< OperatorType > local
std::vector< std::vector< std::string > > info
std::vector< std::vector< std::vector< std::vector< OperatorType > > > > transfer
OperatorType const & localOps(std::size_t loc) const
std::vector< int > hilbert_dimension
std::vector< bool > localSet
void assert_hilbert(std::size_t loc, int dim)
std::vector< std::vector< std::vector< std::vector< OperatorType > > > > outgoing
std::vector< SuperMatrix< Symmetry, Scalar > > construct_Matrix()
std::vector< std::string > get_info() const
std::size_t Hilbert_dimension(std::size_t loc) const
std::vector< std::vector< OperatorType > > const & transferOps(std::size_t n, std::size_t loc) const
void push_local(std::size_t loc, Scalar lambda, OperatorType Op)
std::vector< std::vector< OperatorType > > const & nextn_outOps(std::size_t loc) const
std::size_t size() const
void push_nextn(std::size_t loc, Scalar lambda, OperatorType Op1, OperatorType Trans, OperatorType Op2)
void compress(std::vector< std::vector< std::vector< std::vector< OperatorType > > > > &incoming_compressed, std::vector< std::vector< std::vector< std::vector< OperatorType > > > > &outgoing_compressed)
SiteOperator< Symmetry, Scalar > OperatorType
std::vector< OperatorType > const & tight_inOps(std::size_t loc) const
std::vector< std::vector< std::vector< MatrixType > > > coupling
std::vector< OperatorType > const & tight_outOps(std::size_t loc) const
void scale(double factor, double offset=0.)
Eigen::Matrix< Scalar, Eigen::Dynamic, Eigen::Dynamic > MatrixType
Eigen::SparseMatrix< Scalar_ > data
Definition: SiteOperator.h:41
Symmetry::qType Q
Definition: SiteOperator.h:40