ALPS MPS Codes
Reference documentation.
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Pages
tevol_nn_sim.h
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-2011 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 APP_DMRG_TEVOL_NN_SIM_H
28 #define APP_DMRG_TEVOL_NN_SIM_H
29 
30 #include <cmath>
31 #include <iterator>
32 #include <iostream>
33 
34 #include "dmrg/evolve/te_utils.hpp"
36 
37 
38 // ****** HELPER OBJECTS ******
39 template<class Matrix, class SymmGroup>
40 struct trotter_gate {
41  typedef std::vector<long> idx_t;
42  typedef std::vector<block_matrix<Matrix, SymmGroup> > vgates_t;
43 
44  std::size_t pfirst;
47 
48  trotter_gate(std::size_t L) : idx(L, -1) { }
49 
50  void add_term(std::size_t p, block_matrix<Matrix, SymmGroup> const & block)
51  {
52  assert(idx[p] == -1);
53  vgates.push_back(block);
54  idx[p] = vgates.size()-1;
55  }
56 
57  void clear()
58  {
59  vgates.clear();
60  idx = idx_t(idx.size(), -1);
61  pfirst = 0;
62  }
63 };
64 
66 inline std::ostream& operator<< (std::ostream& os, tevol_order_tag o)
67 {
68  switch (o)
69  {
70  case second_order:
71  os << "Second order Trotter decomposition";
72  break;
73  case fourth_order:
74  os << "Fourth order Trotter decomposition";
75  break;
76  default:
77  os << "uknown Trotter decomposition";
78  }
79  return os;
80 }
81 
82 
83 // ****** SIMULATION CLASS ******
84 template <class Matrix, class SymmGroup>
86 public:
88  Lattice const& lattice_, Model<Matrix, SymmGroup> const& model_,
89  int init_sweep=0)
90  : parms(parms_)
91  , mps(mps_)
92  , lattice(lattice_) // shallow copy
93  , model(model_) // shallow copy
94  , L(lattice.size())
95  , trotter_order(parse_trotter_order((*parms)["te_order"]))
96  , block_terms(hamil_to_blocks(lattice, model))
97  {
98  maquis::cout << "Using nearest-neighbors time evolution." << std::endl;
99  maquis::cout << "Using " << trotter_order << std::endl;
100  maquis::cout << "Time evolution optimization is "
101  << (((*parms)["te_optim"]) ? "enabled" : "disabled")
102  << std::endl;
103 
104  /// alpha coeffiecients and set sequence of Uterms according to trotter order
105  switch (trotter_order){
106  case second_order:
107  {
108  gates_coeff.push_back(std::make_pair(0,0.5)); // 0-term
109  gates_coeff.push_back(std::make_pair(1,1.)); // 1-term
110 
111  Useq.push_back(0); // odd
112  Useq.push_back(1); // even
113  Useq.push_back(0); // odd
114 
115  if ((*parms)["te_optim"])
116  {
117  gates_coeff.push_back(std::make_pair(0,1.)); // 2-term
118 
119  Useq_bmeas.push_back(0); // odd
120  Useq_bmeas.push_back(1); // even
121  Useq_bmeas.push_back(2); // odd
122 
123  Useq_double.push_back(1); // even
124  Useq_double.push_back(2); // odd
125 
126  Useq_ameas.push_back(1); // even
127  Useq_ameas.push_back(0); // odd
128  }
129 
130  maquis::cout << "Sequence initialized with " << Useq.size() << " terms." << std::endl;
131  break;
132  }
133  case fourth_order:
134  {
135  double alpha_1=1./(4.0-pow(4.0,0.33333));
136  double alpha_3=1.-4.0*alpha_1;
137 
138  gates_coeff.push_back(std::make_pair(0,alpha_1*0.5)); // 0-term
139  gates_coeff.push_back(std::make_pair(1,alpha_1)); // 1-term
140  gates_coeff.push_back(std::make_pair(0,alpha_3*0.5)); // 2-term
141  gates_coeff.push_back(std::make_pair(1,alpha_3)); // 3-term
142 
143  Useq.push_back(0); // odd
144  Useq.push_back(1); // even
145  Useq.push_back(0); // odd
146  Useq.push_back(0); // odd
147  Useq.push_back(1); // even
148  Useq.push_back(0); // odd
149  Useq.push_back(2); // odd
150  Useq.push_back(3); // even
151  Useq.push_back(2); // odd
152  Useq.push_back(0); // odd
153  Useq.push_back(1); // even
154  Useq.push_back(0); // odd
155  Useq.push_back(0); // odd
156  Useq.push_back(1); // even
157  Useq.push_back(0); // odd
158 
159  if ((*parms)["te_optim"])
160  {
161  gates_coeff.push_back(std::make_pair(0,alpha_1)); // 4-term
162  gates_coeff.push_back(std::make_pair(0,alpha_3*0.5+alpha_1*0.5)); // 5-term
163 
164  Useq_bmeas.push_back(0); // odd
165  Useq_bmeas.push_back(1); // even
166  Useq_bmeas.push_back(4); // odd
167  Useq_bmeas.push_back(1); // even
168  Useq_bmeas.push_back(5); // odd
169  Useq_bmeas.push_back(3); // even
170  Useq_bmeas.push_back(5); // odd
171  Useq_bmeas.push_back(1); // even
172  Useq_bmeas.push_back(4); // odd
173  Useq_bmeas.push_back(1); // even
174  Useq_bmeas.push_back(4); // odd
175 
176  Useq_double.push_back(1); // even
177  Useq_double.push_back(4); // odd
178  Useq_double.push_back(1); // even
179  Useq_double.push_back(5); // odd
180  Useq_double.push_back(3); // even
181  Useq_double.push_back(5); // odd
182  Useq_double.push_back(1); // even
183  Useq_double.push_back(4); // odd
184  Useq_double.push_back(1); // even
185  Useq_double.push_back(4); // odd
186 
187  Useq_ameas.push_back(1); // even
188  Useq_ameas.push_back(4); // odd
189  Useq_ameas.push_back(1); // even
190  Useq_ameas.push_back(5); // odd
191  Useq_ameas.push_back(3); // even
192  Useq_ameas.push_back(5); // odd
193  Useq_ameas.push_back(1); // even
194  Useq_ameas.push_back(4); // odd
195  Useq_ameas.push_back(1); // even
196  Useq_ameas.push_back(0); // odd
197  }
198  maquis::cout << "Sequence initialized with " << Useq.size() << " terms." << std::endl;
199 
200  break;
201  }
202  default:
203  {
204  throw std::runtime_error("uknown Trotter decomposition");
205  break;
206  }
207  }
208 
209  /// compute the time evolution gates
210  prepare_te_terms(init_sweep);
211  }
212 
213 
214  void prepare_te_terms(unsigned sweep)
215  {
216  double dt = (*parms)["dt"];
217  typename Matrix::value_type I;
218  if (sweep < (*parms)["nsweeps_img"])
220  else
222  typename Matrix::value_type alpha = -I * dt;
223 
224  Uterms.resize(gates_coeff.size(), trotter_gate<Matrix, SymmGroup>(L));
225  for (size_t i=0; i<gates_coeff.size(); ++i) {
226  Uterms[i].clear();
227  Uterms[i].pfirst = gates_coeff[i].first;
228  for (size_t p=gates_coeff[i].first; p<L-1; p+=2){
229  int type1 = lattice.get_prop<int>("type", p);
230  int type2 = lattice.get_prop<int>("type", p+1);
231  if ((*parms)["expm_method"] == "heev")
232  Uterms[i].add_term(p, op_exp_hermitian(model.phys_dim(type1)*model.phys_dim(type2), block_terms[p], gates_coeff[i].second*alpha));
233  else
234  Uterms[i].add_term(p, op_exp(model.phys_dim(type1)*model.phys_dim(type2), block_terms[p], gates_coeff[i].second*alpha));
235  }
236  }
237  }
238 
239  void operator()(unsigned sweep, unsigned nsteps)
240  {
241  iteration_results_.clear();
242 
243  if (nsteps < 2 || !static_cast<bool>((*parms)["te_optim"])) {
244  // nsteps sweeps
245  for (unsigned i=0; i < nsteps; ++i) evolve_time_step(Useq);
246 
247  } else {
248  // one sweep
249  evolve_time_step(Useq_bmeas);
250  // nsteps - 2 sweeps
251  for (unsigned i=1; i < nsteps-1; ++i) evolve_time_step(Useq_double);
252  // one sweep
253  evolve_time_step(Useq_ameas);
254  }
255  }
256 
258  {
259  return iteration_results_;
260  }
261 
262 private:
263  tevol_order_tag parse_trotter_order (std::string const & trotter_param)
264  {
265  if (trotter_param == "second")
266  return second_order;
267  else if (trotter_param == "fourth")
268  return fourth_order;
269  else {
270  throw std::runtime_error("Don't know this Trotter decomposition");
271  return order_unknown;
272  }
273  }
274 
275  void evolve_time_step(std::vector<std::size_t> const & gates_i)
276  {
277  assert(gates_i.size() > 0);
278 
279  for (size_t i=0; i<gates_i.size(); ++i) {
280  if (mps->canonization(true) < mps->length()/2)
281  evolve_l2r(gates_i[i]);
282  else
283  evolve_r2l(gates_i[i]);
284  }
285  }
286 
287  void evolve_l2r(std::size_t gate_index)
288  {
289  std::size_t L = mps->length();
290  std::vector<block_matrix<Matrix, SymmGroup> > const & ops = Uterms[gate_index].vgates;
291  std::vector<long> const & idx = Uterms[gate_index].idx;
292  int pfirst = Uterms[gate_index].pfirst;
293  std::size_t Mmax=(*parms)["max_bond_dimension"];
294  double cutoff=(*parms)["truncation_final"];
295  MPS<Matrix, SymmGroup> const& constmps = *mps;
296 
297  assert(L == idx.size());
298 
299  if (mps->canonization() != pfirst + 1)
300  mps->canonize(pfirst + 1);
301 
302  // TODO: remove pfirst!
303  for (std::size_t p = pfirst; p <= L-1; p += 2)
304  {
305  if (idx[p] != -1)
306  {
307  constmps[p].make_left_paired();
308  constmps[p+1].make_right_paired();
309 
311  gemm(constmps[p].data(), constmps[p+1].data(), v0); // outer product of two sites
312 
313  v1 = contraction::multiply_with_twosite(v0, ops[idx[p]],
314  constmps[p].row_dim(), constmps[p+1].col_dim(),
315  constmps[p].site_dim());
316  truncation_results trunc = compression::replace_two_sites_l2r(*mps, Mmax, cutoff, v1, p);
317  iteration_results_["BondDimension"] << trunc.bond_dimension;
318  iteration_results_["TruncatedWeight"] << trunc.truncated_weight;
319  iteration_results_["TruncatedFraction"] << trunc.truncated_fraction;
320  iteration_results_["SmallestEV"] << trunc.smallest_ev;
321  }
322  mps->move_normalization_l2r(p+1, p+3, DefaultSolver());
323  }
324  mps->canonization(true);
325  assert(mps->canonization() == L-1);
326  // maquis::cout << "Norm loss " << i << ": " << trace(t) << " " << -log(trace(t)) << std::endl;
327  }
328 
329  void evolve_r2l(std::size_t gate_index)
330  {
331  std::size_t L = mps->length();
332  std::vector<block_matrix<Matrix, SymmGroup> > const & ops = Uterms[gate_index].vgates;
333  std::vector<long> const & idx = Uterms[gate_index].idx;
334  int pfirst = Uterms[gate_index].pfirst;
335  std::size_t Mmax=(*parms)["max_bond_dimension"];
336  double cutoff=(*parms)["truncation_final"];
337  MPS<Matrix, SymmGroup> const& constmps = *mps;
338 
339  assert(L == idx.size());
340 
341  int startpos = std::min(L-2-(L-pfirst)%2, L-2);
342  if (mps->canonization() != startpos)
343  mps->canonize(startpos);
344 
345  for (int p = std::min(L-2-(L-pfirst)%2, L-2); p >= pfirst; p -= 2)
346  {
347  if (idx[p] != -1)
348  {
349  constmps[p].make_left_paired();
350  constmps[p+1].make_right_paired();
351 
353  gemm(constmps[p].data(), constmps[p+1].data(), v0); // outer product of two sites
354 
355  v1 = contraction::multiply_with_twosite(v0, ops[idx[p]],
356  constmps[p].row_dim(), constmps[p+1].col_dim(),
357  constmps[p].site_dim());
358  truncation_results trunc = compression::replace_two_sites_r2l(*mps, Mmax, cutoff, v1, p);
359  iteration_results_["BondDimension"] << trunc.bond_dimension;
360  iteration_results_["TruncatedWeight"] << trunc.truncated_weight;
361  iteration_results_["TruncatedFraction"] << trunc.truncated_fraction;
362  iteration_results_["SmallestEV"] << trunc.smallest_ev;
363  }
364  mps->move_normalization_r2l(p, std::max(static_cast<long>(p)-2,0L), DefaultSolver());
365  }
366 
367 
368  mps->canonization(true);
369  assert(mps->canonization() == 0);
370  // maquis::cout << "Norm loss " << i << ": " << trace(t) << " " << -log(trace(t)) << std::endl;
371  }
372 
373 private:
374  DmrgParameters * parms;
376  Lattice lattice;
378  size_t L;
379 
380  results_collector iteration_results_;
381 
382  tevol_order_tag trotter_order;
383  std::vector<block_matrix<Matrix, SymmGroup> > block_terms;
384  std::vector<std::pair<std::size_t,double> > gates_coeff;
385  std::vector<trotter_gate<Matrix, SymmGroup> > Uterms;
386  std::vector<std::size_t> Useq; // trivial sequence
387  std::vector<std::size_t> Useq_double, Useq_bmeas, Useq_ameas; // sequence with two sweeps; meas before; meas after
388 };
389 
390 #endif
void add_term(std::size_t p, block_matrix< Matrix, SymmGroup > const &block)
Definition: tevol_nn_sim.h:50
pimpl for Model
Definition: model.h:96
std::vector< block_matrix< Matrix, SymmGroup > > vgates_t
Definition: tevol_nn_sim.h:42
static truncation_results replace_two_sites_l2r(MPS< Matrix, SymmGroup > &mps, std::size_t Mmax, double cutoff, block_matrix< Matrix, SymmGroup > const &t, std::size_t p)
Definition: compression.h:38
std::vector< block_matrix< Matrix, SymmGroup > > hamil_to_blocks(Lattice const &lat, Model< Matrix, SymmGroup > const &model)
Definition: te_utils.hpp:130
block_matrix< Matrix, SymmGroup > op_exp(Index< SymmGroup > const &phys, block_matrix< Matrix, SymmGroup > M, A const &alpha=1.)
utilities for the preparation of time evolution operators
tevol_order_tag
Definition: tevol_nn_sim.h:65
void clear()
Definition: tevol_nn_sim.h:57
data_type data
void prepare_te_terms(unsigned sweep)
Definition: tevol_nn_sim.h:214
vgates_t vgates
Definition: tevol_nn_sim.h:46
trotter_gate(std::size_t L)
Definition: tevol_nn_sim.h:48
static block_matrix< Matrix, SymmGroup > multiply_with_twosite(block_matrix< Matrix, SymmGroup > const &vec, block_matrix< Matrix, SymmGroup > const &op, Index< SymmGroup > const &left_i, Index< SymmGroup > const &right_i, Index< SymmGroup > const &phys_i)
Definition: contractions.h:622
Definition: mps.h:40
T get_prop(std::string property, pos_t site) const
Definition: lattice.h:103
nearest_neighbors_evolver(DmrgParameters *parms_, MPS< Matrix, SymmGroup > *mps_, Lattice const &lattice_, Model< Matrix, SymmGroup > const &model_, int init_sweep=0)
Definition: tevol_nn_sim.h:87
void operator()(unsigned sweep, unsigned nsteps)
Definition: tevol_nn_sim.h:239
std::size_t pfirst
Definition: tevol_nn_sim.h:44
static truncation_results replace_two_sites_r2l(MPS< Matrix, SymmGroup > &mps, std::size_t Mmax, double cutoff, block_matrix< Matrix, SymmGroup > const &t, std::size_t p)
Definition: compression.h:62
std::vector< long > idx_t
Definition: tevol_nn_sim.h:41
void gemm(block_matrix< Matrix1, SymmGroup > const &A, block_matrix< Matrix2, SymmGroup > const &B, block_matrix< Matrix3, SymmGroup > &C)
results_collector const & iteration_results() const
Definition: tevol_nn_sim.h:257
std::ostream & operator<<(std::ostream &os, tevol_order_tag o)
Definition: tevol_nn_sim.h:66
block_matrix< Matrix, SymmGroup > op_exp_hermitian(Index< SymmGroup > const &phys, block_matrix< Matrix, SymmGroup > M, A const &alpha=1.)
pimpl resolved Lattice
Definition: lattice.h:84