27 #ifndef APP_TE_UTILS_H
28 #define APP_TE_UTILS_H
51 typedef std::map<std::size_t, std::set<std::size_t> > pos_where_t;
53 typedef std::map<std::size_t, std::vector<term_t> > pos_terms_t;
55 std::vector<std::vector<term_t> > ret;
56 pos_where_t pos_where;
57 pos_terms_t pos_terms;
59 for (
int i=0; i<hamil_terms.size(); ++i)
61 if (hamil_terms[i].size() == 1) {
62 pos_terms[hamil_terms[i].position(0)].push_back(hamil_terms[i]);
66 term_t term = hamil_terms[i];
69 for (
int n=0; n<ret.size() && !used; ++n)
72 for (
int j=0; j<ret[n].size() && !
overlap; ++j)
74 if ( ret[n][j].site_match(term) )
break;
75 overlap = ret[n][j].overlap(term);
79 ret[n].push_back(term);
80 for (
int k=0; k<term.size(); ++k)
81 pos_where[term.position(k)].insert(n);
87 ret.push_back( std::vector<term_t>(1, term) );
89 for (
int k=0; k<term.size(); ++k)
90 pos_where[term.position(k)].insert(ret.size()-1);
95 for (
typename pos_terms_t::const_iterator it = pos_terms.begin();
96 it != pos_terms.end(); ++it)
98 double coeff = 1. / pos_where[it->first].size();
100 for (
typename std::set<std::size_t>::const_iterator it2 = pos_where[it->first].begin();
101 it2 != pos_where[it->first].end(); ++it2)
102 for (
int k=0; k<it->second.size(); ++k)
104 term_t tmp_term = it->second[k];
105 tmp_term.coeff *= coeff;
106 ret[*it2].push_back(tmp_term);
111 for (
int n=0; n<ret.size(); ++n)
112 std::sort(ret[n].begin(), ret[n].end());
118 template <
class Matrix,
class SymmGroup>
124 op_kron(phys1_i, phys2_i, op1, op2, bond_op);
129 template <
class Matrix,
class SymmGroup>
132 std::size_t L = lat.
size();
133 std::vector<block_matrix<Matrix, SymmGroup> > ret_blocks(L-1);
139 for (
int i=0; i<hamil_terms.size(); ++i)
141 term_t term = hamil_terms[i];
142 term.canonical_order();
143 std::size_t pos1 = term.position(0);
144 int type = lat.
get_prop<
int>(
"type", pos1);
145 int type_p1, type_m1;
146 if (pos1 < L-1) type_p1 = lat.
get_prop<
int>(
"type", pos1+1);
147 if (pos1 > 0) type_m1 = lat.
get_prop<
int>(
"type", pos1-1);
148 if (term.size() == 1) {
149 if (pos1 != 0 && pos1 != L-1)
153 tag_handler->get_op(term.operator_tag(0)), model.
phys_dim(type),
158 tag_handler->get_op(term.operator_tag(0)), model.
phys_dim(type));
159 }
else if (term.size() == 2) {
160 assert( std::abs(term.position(0)-term.position(1)) == 1 );
162 tag_handler->get_op(term.operator_tag(0)), model.
phys_dim(type),
163 tag_handler->get_op(term.operator_tag(1)), model.
phys_dim(type_p1));
170 template <
class Matrix,
class SymmGroup>
176 typedef boost::shared_ptr<op_table_t> op_table_ptr;
179 typedef boost::tuple<std::size_t, std::size_t, tag_type, typename Matrix::value_type> pretensor_value;
180 typedef std::vector<pretensor_value> pretensor_t;
181 typedef std::vector<pretensor_t> prempo_t;
185 std::size_t pos1_, std::size_t pos2_,
Lattice const& lat_)
186 : phys1(phys1_), phys2(phys2_)
187 , pos1(pos1_), pos2(pos2_), L(pos2-pos1+1)
189 , type1(lattice.get_prop<int>(
"type", pos1))
190 , type2(lattice.get_prop<int>(
"type", pos2))
191 , n_boso(0), n_ferm(0)
197 throw std::runtime_error(
"time evolution requires at max two-site bond term.");
203 if (term.size() == 2)
210 throw std::runtime_error(
"Operator k not matching any valid position.");
213 fermionic_bond += term.
coeff * bond_op;
216 bosonic_bond += term.
coeff * bond_op;
222 std::vector<tag_type>
const& ident, std::vector<tag_type>
const& fill,
223 op_table_ptr op_table)
const
225 std::size_t maximum_b = 0;
229 std::vector<op_t> left_ops, right_ops;
230 exp_and_split(bosonic_bond, alpha, left_ops, right_ops);
232 maximum_b = add_to_mpo(prempo, maximum_b, left_ops, right_ops, 1., ident, op_table);
238 std::vector<op_t> left_ops, right_ops;
239 exp_and_split(fermionic_bond, alpha, left_ops, right_ops);
241 maximum_b = add_to_mpo(prempo, maximum_b, left_ops, right_ops, .5, ident, op_table);
242 maximum_b = add_to_mpo(prempo, maximum_b, left_ops, right_ops, .5, fill, op_table);
247 std::vector<op_t> left_ops, right_ops;
248 exp_and_split(fermionic_bond, -alpha, left_ops, right_ops);
250 maximum_b = add_to_mpo(prempo, maximum_b, left_ops, right_ops, .5, ident, op_table);
251 maximum_b = add_to_mpo(prempo, maximum_b, left_ops, right_ops, -.5, fill, op_table);
257 for (
size_t p=0; p<L; ++p) {
260 boost::tie(nrows, ncols) =
rcdim(prempo[p]);
271 void exp_and_split(op_t
const& bond_op,
typename Matrix::value_type
const & alpha,
272 std::vector<op_t> & left_ops, std::vector<op_t> & right_ops)
const
277 typedef typename alps::numeric::associated_real_diagonal_matrix<Matrix>::type diag_matrix;
280 svd(bond_exp, U, V, S);
282 gemm(U, Ssqrt, left);
283 gemm(Ssqrt, V, right);
285 for(std::size_t k = 0; k < S.
n_blocks(); ++k){
286 int keep = std::find_if(S[k].diagonal().first, S[k].diagonal().second, boost::lambda::_1 < 1e-10)-S[k].diagonal().first;
296 assert(left_ops.size() == right_ops.size());
299 std::size_t add_to_mpo(prempo_t & prempo, std::size_t maximum_b,
300 std::vector<op_t>
const& left_ops, std::vector<op_t>
const& right_ops,
301 typename Matrix::value_type s, std::vector<tag_type> fill, op_table_ptr op_table)
const
303 for (std::size_t i=0; i<left_ops.size(); ++i)
305 std::size_t b = (maximum_b++);
307 std::pair<tag_type, typename Matrix::value_type> left_tag, right_tag;
308 left_tag = op_table->checked_register(left_ops[i]);
309 right_tag = op_table->checked_register(right_ops[i]);
311 s *= left_tag.second * right_tag.second;
313 prempo[0].push_back ( pretensor_value(0, b, left_tag.first, s ) );
314 prempo[L-1].push_back( pretensor_value(b, 0, right_tag.first, 1.) );
315 for (std::size_t p=1; p<L-1; ++p)
316 prempo[p].push_back( pretensor_value(b, b, fill[lattice.
get_prop<
int>(
"prop",pos1+p)], 1.) );
322 std::size_t pos1, pos2, L;
325 std::size_t n_boso, n_ferm;
326 op_t bosonic_bond, fermionic_bond;
330 template <
class Matrix,
class SymmGroup>
333 typename Matrix::value_type
const & alpha = 1)
337 typedef boost::shared_ptr<op_table_t> op_table_ptr;
339 typedef boost::tuple<std::size_t, std::size_t, tag_type, typename Matrix::value_type> pretensor_value;
340 typedef std::vector<pretensor_value> pretensor_t;
342 op_table_ptr original_op_table = model.
operators_table()->get_operator_table();
343 op_table_ptr new_op_table(
new op_table_t() );
345 size_t length = lat.
size();
348 for (
int type=0; type<ident.size(); ++type) {
349 ident[type] = new_op_table->register_op( model.
identity_matrix(type) );
350 fill[type] = new_op_table->register_op( model.
filling_matrix(type) );
354 std::vector<bool> used_p(length,
false);
356 for (
int n=0; n<hamil_terms.size(); )
358 if (hamil_terms[n].size() != 2)
throw std::runtime_error(
"hamiltonian terms have to be sorted with two-site bond terms before site terms.");
359 int pos1 = hamil_terms[n].position(0);
360 int pos2 = hamil_terms[n].position(1);
362 int type1 = lat.
get_prop<
int>(
"type", pos1);
363 int type2 = lat.
get_prop<
int>(
"type", pos2);
367 maker.
add_term(hamil_terms[n], model);
370 for (; k<hamil_terms.size() && hamil_terms[n].site_match(hamil_terms[k]); ++k)
371 maker.add_term(hamil_terms[k], model);
374 for (
size_t p=0; p<pos2-pos1+1; ++p) {
376 swap(mpo[pos1+p], block_mpo[p]);
377 used_p[pos1+p] =
true;
385 for (std::size_t p=0; p<length; ++p) {
387 pretensor_t preident(1, pretensor_value(0, 0, ident[lat.
get_prop<
int>(
"type", p)], 1.) );
std::vector< std::vector< term_descriptor< T > > > separate_hamil_terms(std::vector< term_descriptor< T > > const &hamil_terms)
op_t const & filling_matrix(size_t type=0) const
definition of Lattice base class
functions to compress the MPS
terms_type const & hamiltonian_terms() const
impl_type::table_ptr table_ptr
void add_term(term_t const &term, Model< Matrix, SymmGroup > const &model)
size_type n_blocks() const
definition of Model base class
tag_detail::tag_type tag_type
std::vector< block_matrix< Matrix, SymmGroup > > hamil_to_blocks(Lattice const &lat, Model< Matrix, SymmGroup > const &model)
op_t const & identity_matrix(size_t type=0) const
void swap(MPSTensor< Matrix, SymmGroup > &x, MPSTensor< Matrix, SymmGroup > &y)
functions to manipulate MPOs
declaration of block_matrix class
exp_mpo_maker(Index< SymmGroup > phys1_, Index< SymmGroup > phys2_, std::size_t pos1_, std::size_t pos2_, Lattice const &lat_)
std::vector< block_matrix< Matrix, SymmGroup > > reshape_right_to_list(Index< SymmGroup > const &phys, block_matrix< Matrix, SymmGroup > const &A)
block_matrix< Matrix, SymmGroup > reshape_2site_op(Index< SymmGroup > const &phys1, Index< SymmGroup > const &phys2, block_matrix< Matrix, SymmGroup > const &A)
void op_kron(Index< SymmGroup > const &phys_A, Index< SymmGroup > const &phys_B, block_matrix< Matrix1, SymmGroup > const &A, block_matrix< Matrix1, SymmGroup > const &B, block_matrix< Matrix2, SymmGroup > &C)
tag_type operator_tag(size_type i) const
block_matrix< Matrix, SymmGroup > sqrt(block_matrix< Matrix, SymmGroup > m)
void resize_block(charge r, charge c, size_type new_r, size_type new_c, bool pretend=false)
int maximum_vertex_type() const
MPS< Matrix, SymmGroup >::scalar_type overlap(MPS< Matrix, SymmGroup > const &mps1, MPS< Matrix, SymmGroup > const &mps2)
std::vector< block_matrix< Matrix, SymmGroup > > reshape_left_to_list(Index< SymmGroup > const &phys, block_matrix< Matrix, SymmGroup > const &A)
T get_prop(std::string property, pos_t site) const
void svd(block_matrix< Matrix, SymmGroup > const &M, block_matrix< Matrix, SymmGroup > &U, block_matrix< Matrix, SymmGroup > &V, block_matrix< DiagMatrix, SymmGroup > &S)
Index< SymmGroup > const & right_basis() const
std::pair< size_t, size_t > rcdim(Vector const &pm)
block_matrix< Matrix, SymmGroup > term2block(typename Matrix::value_type const &scale, block_matrix< Matrix, SymmGroup > const &op1, Index< SymmGroup > const &phys1_i, block_matrix< Matrix, SymmGroup > const &op2, Index< SymmGroup > const &phys2_i)
table_ptr operators_table() const
MPO< Matrix, SymmGroup > exp_mpo(typename Matrix::value_type const &alpha, std::vector< tag_type > const &ident, std::vector< tag_type > const &fill, op_table_ptr op_table) const
Index< SymmGroup > const & phys_dim(size_t type=0) const
pos_type position(size_type i) const
void canonical_order()
utilities
functions to reshape the representation of data in MPSTensor
void gemm(block_matrix< Matrix1, SymmGroup > const &A, block_matrix< Matrix2, SymmGroup > const &B, block_matrix< Matrix3, SymmGroup > &C)
block_matrix< Matrix, SymmGroup > op_exp_hermitian(Index< SymmGroup > const &phys, block_matrix< Matrix, SymmGroup > M, A const &alpha=1.)
Index< SymmGroup > const & left_basis() const
MPO< Matrix, SymmGroup > make_exp_mpo(Lattice const &lat, Model< Matrix, SymmGroup > const &model, std::vector< term_descriptor< typename Matrix::value_type > > const &hamil_terms, typename Matrix::value_type const &alpha=1)