1#ifndef DMRG_HAMILTONIAN_TERMS
2#define DMRG_HAMILTONIAN_TERMS
10#include "numeric_limits.h"
18 typename Symmetry::qType
qvac = Symmetry::qvacuum();
19 typedef Eigen::Matrix<Scalar, Eigen::Dynamic, Eigen::Dynamic>
MatrixType;
25 std::vector<OperatorType>
local;
48 std::vector<std::vector<std::string>>
info;
64 std::vector<std::vector<std::vector<std::vector<OperatorType>>>>
outgoing;
70 std::vector<std::vector<std::vector<std::vector<OperatorType>>>>
incoming;
76 std::vector<std::vector<std::vector<std::vector<OperatorType>>>>
transfer;
82 std::vector<std::vector<std::vector<MatrixType>>>
coupling;
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);
173 std::vector<std::string>
get_info()
const;
199 void scale(
double factor,
double offset=0.);
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];}
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];}
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];}
244 std::vector<std::vector<OperatorType>>
const&
nextn_inOps(std::size_t loc)
const {
return incoming[1][loc];}
254 if(hilbert_dimension[loc] == 0)
256 hilbert_dimension[loc] =
dim;
260 assert(hilbert_dimension[loc] ==
dim and
"Dimensions of operator and local Hilbert space do not match!");
267 assert(loc < N_sites and
"Chosen lattice site out of bounds");
273 assert(outOp.
Q == qvac and
"Local operator is not a singlet");
274 assert_hilbert(loc, outOp.
data.rows());
277 local[loc] += lambda * outOp;
281 local[loc] = lambda * outOp;
282 localSet[loc] =
true;
288 assert(transOps.size() == n-1 and
"Distance does not match to number of transfer operators!");
291 for(
int i=n_max; i<n; ++i)
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);
303 std::ptrdiff_t transptr;
307 if(coupling[0][loc].size() == 0)
309 Eigen::Matrix<Scalar, Eigen::Dynamic, Eigen::Dynamic> matrix = Eigen::Matrix<Scalar, Eigen::Dynamic, Eigen::Dynamic>::Zero(1,1);
310 std::vector<OperatorType> temp;
312 coupling[0][loc].push_back(matrix);
313 outgoing[0][loc].push_back(temp);
314 incoming[0][(loc+1)%N_sites].push_back(temp);
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())
322 transfer[n-1][loc].push_back(transOps);
323 for(std::size_t t=0; t<n-1; ++t)
325 assert_hilbert((loc+t+1)%N_sites, transOps[t].data.rows());
328 Eigen::Matrix<Scalar, Eigen::Dynamic, Eigen::Dynamic> matrix = Eigen::Matrix<Scalar, Eigen::Dynamic, Eigen::Dynamic>::Zero(1,1);
329 std::vector<OperatorType> temp;
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);
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())
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();
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())
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();
358 coupling[n-1][loc][transptr](outptr, inptr) += lambda;
374save_label(std::size_t loc,
const std::string &label)
376 assert(loc < N_sites and
"Chosen lattice site out of bounds");
379 info[loc].push_back(label);
386 std::vector<std::string> res(N_sites);
387 for(std::size_t loc=0; loc<N_sites; ++loc)
389 std::stringstream ss;
390 if (info[loc].size()>0)
392 std::copy(info[loc].begin(), info[loc].end()-1, std::ostream_iterator<std::string>(ss,
","));
393 ss << info[loc].back();
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₀");
429 assert(loc < N_sites and
"Chosen lattice site out of bounds");
430 return hilbert_dimension[loc];
436 push(0, loc, lambda, Op, {}, Op);
442 push(1, loc, lambda, Op1, {}, Op2);
448 push(2, loc, lambda, Op1, {Trans}, Op2);
452compress(std::vector<std::vector<std::vector<std::vector<OperatorType>>>> &outgoing_compressed, std::vector<std::vector<std::vector<std::vector<OperatorType>>>> &incoming_compressed)
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)
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)
464 if(outgoing[0][loc][0].size() < incoming[0][(loc+1)%N_sites][0].size())
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];
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];
480 for(std::size_t n=1; n<n_max; ++n)
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)
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)
490 if(outgoing[n][loc][t].size() < incoming[n][(loc+n+1)%N_sites][t].size())
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];
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];
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);
512 std::vector<SuperMatrix<Symmetry, Scalar>> G;
513 for (std::size_t loc=0; loc<N_sites; ++loc)
516 if(hilbert_dimension[loc] == 0)
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]);
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]);
543 std::size_t rows = 2;
544 std::size_t cols = 2;
545 if(incoming_compressed[0][loc].size() > 0)
547 rows += incoming_compressed[0][loc][0].size();
549 if(outgoing_compressed[0][loc].size() > 0)
551 cols += outgoing_compressed[0][loc][0].size();
553 for(std::size_t n=1; n<n_max; ++n)
555 for(std::size_t t=0; t<incoming_compressed[n][loc].size(); ++t)
557 rows += incoming_compressed[n][loc][t].size();
559 for(std::size_t t=0; t<outgoing_compressed[n][loc].size(); ++t)
561 cols += outgoing_compressed[n][loc][t].size();
564 for(std::size_t m=0; m<n; ++m)
566 for(std::size_t t=0; t<transfer[n][(N_sites+loc-m-1)%N_sites].size(); ++t)
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();
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]);
580 std::size_t current = 1;
581 if(incoming_compressed[0][loc].size() > 0)
583 for(std::size_t i=0; i<incoming_compressed[0][loc][0].size(); ++i)
586 S(current++, 0) = incoming_compressed[0][loc][0][i];
590 for(std::size_t n=1; n<n_max; ++n)
592 for(std::size_t t=0; t<incoming_compressed[n][loc].size(); ++t)
594 for(std::size_t i=0; i<incoming_compressed[n][loc][t].size(); ++i)
597 S(current++, 0) = incoming_compressed[n][loc][t][i];
600 std::size_t temp = current;
602 for(std::size_t m=0; m<n; ++m)
604 for(std::size_t t=0; t<transfer[n][(N_sites+loc-m-1)%N_sites].size(); ++t)
606 current += outgoing_compressed[n][(N_sites+loc-m-1)%N_sites][t].size();
619 S(rows-1,0) = local[loc];
625 if(outgoing_compressed[0][loc].size() > 0)
627 for(std::size_t i=0; i<outgoing_compressed[0][loc][0].size(); ++i)
630 S(rows-1, current++) = outgoing_compressed[0][loc][0][i];
634 for(std::size_t n=1; n<n_max; ++n)
636 std::size_t temp = current;
638 for(std::size_t m=0; m<n; ++m)
640 for(std::size_t t=0; t<transfer[n][(N_sites+loc-m-1)%N_sites].size(); ++t)
642 current += outgoing_compressed[n][(N_sites+loc-m-1)%N_sites][t].size();
649 for(std::size_t t=0; t<outgoing_compressed[n][loc].size(); ++t)
651 for(std::size_t i=0; i<outgoing_compressed[n][loc][t].size(); ++i)
654 S(rows-1, current++) = outgoing_compressed[n][loc][t][i];
659 S(rows-1,cols-1) = Id;
662 std::size_t current_row = 1;
663 std::size_t current_col = 1;
664 if(incoming_compressed[0][loc].size() > 0)
666 current_row += incoming_compressed[0][loc][0].size();
669 if(outgoing_compressed[0][loc].size() > 0)
671 current_col += outgoing_compressed[0][loc][0].size();
673 for(std::size_t n=1; n<n_max; ++n)
675 for(std::size_t t=0; t<incoming_compressed[n][loc].size(); ++t)
677 current_row += incoming_compressed[n][loc][t].size();
679 for(std::size_t m=0; m<n; ++m)
681 for(std::size_t t=0; t<transfer[n][(N_sites + loc - n + m) % N_sites].size(); ++t)
683 for(std::size_t i=0; i<outgoing_compressed[n][(N_sites + loc - n + m)%N_sites][t].size(); ++i)
686 S(current_row++, current_col++) = transfer[n][(N_sites + loc - n + m)%N_sites][t][n-1-m];
690 for(std::size_t t=0; t<outgoing_compressed[n][loc].size(); ++t)
692 current_col += outgoing_compressed[n][loc][t].size();
698 if (OPEN_BC and loc==0)
700 G.push_back(S.row(S.rows()-1));
702 else if (OPEN_BC and loc==N_sites-1)
704 G.push_back(S.col(0));
716scale (
double factor,
double offset)
718 if (std::abs(factor-1.) > ::mynumeric_limits<double>::epsilon())
720 for (std::size_t loc=0; loc<N_sites; ++loc)
722 local[loc] = factor * local[loc];
723 for(std::size_t n=0; n<n_max; ++n)
725 for(std::size_t t=0; t<coupling[n][loc].size(); ++t)
727 coupling[n][loc][t] *= factor;
733 if (std::abs(offset) > ::mynumeric_limits<double>::epsilon())
735 for(std::size_t loc=0; loc<N_sites; ++loc)
737 if(hilbert_dimension[loc] > 0)
740 Id.
data = Matrix<Scalar,Dynamic,Dynamic>::Identity(hilbert_dimension[loc],hilbert_dimension[loc]).sparseView();
741 push_local(loc, offset, Id);
747template<
typename Symmetry,
typename Scalar>
748template<
typename OtherScalar>
754 for(std::size_t loc=0; loc<N_sites; ++loc)
756 for(std::size_t i=0; i<info[loc].size(); ++i)
760 other.
push_local(loc, 1., local[loc].
template cast<OtherScalar>());
762 if(outgoing[0][loc].size() > 0)
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)
767 for(std::size_t j=0; j<other_coupling.cols(); ++j)
771 other.
push_tight(loc, other_coupling(i,j), other_out, other_in);
775 for(std::size_t n=1; n<n_max; ++n)
777 for(std::size_t t=0; t<transfer[n][loc].size(); ++t)
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)
782 for(std::size_t j=0; j<other_coupling.cols(); ++j)
786 std::vector<SiteOperator<Symmetry, OtherScalar>> other_transfer;
787 for(std::size_t k=0; k<transfer[n][loc][t].size(); ++k)
789 other_transfer.push_back(transfer[n][loc][t][k].
template cast<OtherScalar>());
791 other.
push(n+1, loc, other_coupling(i,j), other_out, other_transfer, other_in);
size_t dim(const PivotMatrix0< Symmetry, Scalar, MpoScalar > &H)
void set_name(const std::string &label_in)
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)
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
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