ALPS MPS Codes
Reference documentation.
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Pages
joins.hpp
Go to the documentation of this file.
1 /*****************************************************************************
2  *
3  * ALPS MPS DMRG Project
4  *
5  * Copyright (C) 2013 Institute for Theoretical Physics, ETH Zurich
6  * 2011-2012 by Michele Dolfi <dolfim@phys.ethz.ch>
7  *
8  * This software is part of the ALPS Applications, published under the ALPS
9  * Application License; you can use, redistribute it and/or modify it under
10  * the terms of the license, either version 1 or (at your option) any later
11  * version.
12  *
13  * You should have received a copy of the ALPS Application License along with
14  * the ALPS Applications; see the file LICENSE.txt. If not, the license is also
15  * available from http://alps.comp-phys.org/.
16  *
17  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
18  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
19  * FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT
20  * SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE
21  * FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE,
22  * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
23  * DEALINGS IN THE SOFTWARE.
24  *
25  *****************************************************************************/
26 
27 #ifndef JOINS_H
28 #define JOINS_H
29 
31 
32 template <class Matrix, class SymmGroup>
34  boundary_flag_t boundary_f=no_boundary_f)
35 {
36  assert(m1.site_dim() == m2.site_dim());
37 
38  Index<SymmGroup> const& phys_i = m1.site_dim();
39 
40  m1.make_left_paired();
41  m2.make_left_paired();
42 
43 
45  // phys_i is untouched
46  ret.phys_i = phys_i;
47 
48  // computing new left_i
49  ret.left_i = m1.left_i;
50  if (boundary_f != l_boundary_f) {
51  for (typename Index<SymmGroup>::const_iterator it = m2.left_i.begin();
52  it != m2.left_i.end(); ++it) {
53  if (ret.left_i.has(it->first))
54  ret.left_i[ret.left_i.position(it->first)].second += it->second;
55  else
56  ret.left_i.insert(*it);
57  }
58  }
59 
60  // computing new right_i
61  ret.right_i = m1.right_i;
62  if (boundary_f != r_boundary_f) {
63  for (typename Index<SymmGroup>::const_iterator it = m2.right_i.begin();
64  it != m2.right_i.end(); ++it) {
65  if (ret.right_i.has(it->first))
66  ret.right_i[ret.right_i.position(it->first)].second += it->second;
67  else
68  ret.right_i.insert(*it);
69  }
70  }
71 
72  ProductBasis<SymmGroup> out_left_pb(phys_i, ret.left_i);
73  Index<SymmGroup> const& out_right = ret.right_i;
74 
75  using std::size_t;
76 
77  for (size_t t=0; t<2; ++t) // t=0 --> mps1, t=1 --> mps2
78  {
79  MPSTensor<Matrix, SymmGroup> const & m = (t==0) ? m1 : m2;
80  ProductBasis<SymmGroup> in_left(phys_i, m.row_dim());
81 
82  for (size_t b = 0; b < m.data().n_blocks(); ++b) {
83  typename SymmGroup::charge const& sl_charge = m.data().left_basis()[b].first; // phys + left
84  typename SymmGroup::charge const& r_charge = m.data().right_basis()[b].first; // right
85  size_t out_r_charge_i = out_right.position(r_charge);
86 
87  if (!ret.data().has_block(sl_charge, r_charge))
88  ret.data().insert_block(Matrix(out_left_pb.size(sl_charge), out_right[out_r_charge_i].second),
89  sl_charge, r_charge);
90 
91  Matrix & nb = ret.data()(sl_charge, r_charge);
92 
93  size_t in_r_size = m.data().right_basis()[b].second;
94  size_t out_r_offset = 0;
95  if (t == 1 && boundary_f != r_boundary_f)
96  out_r_offset += m1.col_dim().size_of_block(r_charge, true);
97 
98  for (size_t s=0; s<phys_i.size(); ++s) {
99  typename SymmGroup::charge const& s_charge = phys_i[s].first;
100  typename SymmGroup::charge l_charge = SymmGroup::fuse(sl_charge, -s_charge); // left
101 
102  if (!m.row_dim().has(l_charge))
103  continue;
104 
105  size_t in_l_size = m.row_dim().size_of_block(l_charge, true);
106  size_t in_l_offset = in_left(s_charge, l_charge);
107 
108  size_t out_l_size = ret.row_dim().size_of_block(l_charge, true);
109  size_t out_l_offset = out_left_pb(s_charge, l_charge);
110  if (t == 1 && boundary_f != l_boundary_f)
111  out_l_offset += m1.row_dim().size_of_block(l_charge, true);
112 
113  for (size_t ss=0; ss<phys_i[s].second; ++ss) {
114  copy_block(m.data()[b], in_l_offset+ss*in_l_size, 0,
115  nb, out_l_offset+ss*out_l_size, out_r_offset,
116  in_l_size, in_r_size);
117  }
118  }
119  }
120  }
121 
122  // check right_pairing
123  assert( weak_equal(ret.right_i, ret.data().right_basis()) );
124 
125  return ret;
126 }
127 
128 
129 #endif
void make_left_paired() const
Definition: mpstensor.hpp:173
Index< SymmGroup > const & col_dim() const
Definition: mpstensor.hpp:161
base_t::const_iterator const_iterator
size_t size(charge pc) const
Index< SymmGroup > const & row_dim() const
Definition: mpstensor.hpp:155
Index< SymmGroup > phys_i
Definition: mpstensor.h:141
bool weak_equal(Index< SymmGroup > const &a, Index< SymmGroup > const &b)
declaration of the MPSTensor class
std::size_t position(charge c) const
Index< SymmGroup > const & site_dim() const
Definition: mpstensor.hpp:149
Index< SymmGroup > left_i
Definition: mpstensor.h:141
boundary_flag_t
Definition: mpstensor.h:37
Index< SymmGroup > right_i
Definition: mpstensor.h:141
block_matrix< Matrix, SymmGroup > & data()
Definition: mpstensor.hpp:423
MPSTensor< Matrix, SymmGroup > join(MPSTensor< Matrix, SymmGroup > const &m1, MPSTensor< Matrix, SymmGroup > const &m2, boundary_flag_t boundary_f=no_boundary_f)
Definition: joins.hpp:33
T fuse(const A &ind, T d)
Fuse indices n[i] into one p = n[i] d^i.