27 #ifndef APP_ALPS_MODEL_H
28 #define APP_ALPS_MODEL_H
34 #include <alps/parameter.h>
35 #include <alps/lattice.h>
36 #include <alps/model.h>
40 #include <boost/tokenizer.hpp>
41 #include <boost/regex.hpp>
42 #include <boost/container/flat_map.hpp>
54 template <
class Matrix,
class SymmGroup>
59 typedef alps::SiteOperator SiteOperator;
60 typedef alps::BondOperator BondOperator;
62 typedef typename Matrix::value_type value_type;
64 typedef boost::multi_array<value_type,2> alps_matrix;
65 typedef std::map<std::string, int> qn_map_type;
68 typedef alps::graph_helper<> graph_type;
70 typedef boost::tokenizer<boost::char_separator<char> > tokenizer;
94 typedef typename SymmGroup::charge
charge;
99 , raw_lattice(lattice_)
101 , model(lattice, parms, true)
106 size_t num_vertex_types = alps::maximum_vertex_type(lattice.graph())+1;
107 symm_basis.reserve(num_vertex_types);
108 basis_descriptors.reserve(num_vertex_types);
109 site_bases.reserve(num_vertex_types);
112 for (
int type=0; type<=alps::maximum_vertex_type(lattice.graph()); ++type) {
113 std::set<std::string> type_qn = model.quantum_numbers(type);
114 all_qn.insert(type_qn.begin(), type_qn.end());
117 if (parms.defined(
"CONSERVED_QUANTUMNUMBERS")) {
118 boost::char_separator<char> sep(
" ,");
119 std::string qn_string = parms[
"CONSERVED_QUANTUMNUMBERS"];
120 tokenizer qn_tokens(qn_string, sep);
122 for (tokenizer::iterator it=qn_tokens.begin(); it != qn_tokens.end(); it++) {
123 if (parms.defined(*it +
"_total")) {
124 if (all_qn.find(*it) != all_qn.end())
125 all_conserved_qn.insert( std::make_pair(*it, n++) );
127 throw std::runtime_error(
"quantumnumber "+(*it)+
" not defined in the model.");
133 for (
int type=0; type<=alps::maximum_vertex_type(lattice.graph()); ++type) {
134 basis_descriptors.push_back(model.site_basis(type));
135 site_bases.push_back(alps::site_basis<I>(basis_descriptors[type]));
139 for (
int i=0; i<symm_basis[type].size(); ++i) {
140 charge c = symm_basis[type].charge(i);
141 size_t bsize = symm_basis[type].block_size(i);
147 int sign = (alps::is_fermionic(basis_descriptors[type], site_bases[type][i])) ? -1 : 1;
150 fill(symm_basis[type].coords(i), symm_basis[type].coords(i)) = sign;
158 std::vector<std::vector<std::pair<value_type, tag_type> > > site_terms(num_vertex_types);
159 for (graph_type::site_iterator it=lattice.sites().first; it!=lattice.sites().second; ++it) {
160 int p = lattice.vertex_index(*it);
161 int type = lattice.site_type(*it);
163 if (site_terms[type].size() == 0) {
164 typedef std::vector<boost::tuple<alps::expression::Term<value_type>,alps::SiteOperator> > V;
165 V ops = model.site_term(type).template templated_split<value_type>();
167 for (
int n=0; n<ops.size(); ++n) {
168 SiteOperator op = boost::get<1>(ops[n]);
170 if (match == operators.end())
171 match = register_operator(op, type, parms);
175 term.coeff = boost::get<0>(ops[n]);
176 term.is_fermionic =
false;
177 term.push_back( boost::make_tuple(p, match->second) );
178 expression_coeff.insert( std::make_pair(term.coeff, value_type()) );
179 expression_terms.push_back(term);
205 for (graph_type::bond_iterator it=lattice.bonds().first; it!=lattice.bonds().second; ++it) {
206 int p_s = lattice.source(*it);
207 int p_t = lattice.target(*it);
208 int type = lattice.bond_type(*it);
209 int type_s = lattice.site_type(lattice.source(*it));
210 int type_t = lattice.site_type(lattice.target(*it));
212 bool wrap_pbc = boost::get(alps::boundary_crossing_t(), lattice.graph(), *it);
214 BondOperator bondop = model.bond_term(type);
216 typedef std::vector<boost::tuple<alps::expression::Term<value_type>,alps::SiteOperator,alps::SiteOperator > > V;
217 alps::SiteBasisDescriptor<I>
const& b1 = basis_descriptors[type_s];
218 alps::SiteBasisDescriptor<I>
const& b2 = basis_descriptors[type_t];
221 V ops = bondop.template templated_split<value_type>(b1,b2);
222 for (
typename V::iterator tit=ops.begin(); tit!=ops.end();++tit) {
223 SiteOperator op1 = boost::get<1>(*tit);
224 SiteOperator op2 = boost::get<2>(*tit);
227 if (match1 == operators.end())
228 match1 = register_operator(op1, type_s, parms);
230 if (match2 == operators.end())
231 match2 = register_operator(op2, type_t, parms);
233 bool with_sign = fermionic(b1, op1, b2, op2);
236 term.coeff = boost::get<0>(*tit);
237 term.is_fermionic = with_sign;
241 if (with_sign && !wrap_pbc) {
243 std::pair<tag_type, value_type> ptag = tag_handler->get_product_tag(operators[
opkey_type(
"fill",type_s)],
246 term.coeff *= ptag.second;
248 if (with_sign && wrap_pbc)
249 term.coeff *= value_type(-1.);
250 term.push_back( boost::make_tuple(p_s, mytag) );
254 if (with_sign && wrap_pbc) {
256 std::pair<tag_type, value_type> ptag = tag_handler->get_product_tag(operators[
opkey_type(
"fill",type_t)],
259 term.coeff *= ptag.second;
261 term.push_back( boost::make_tuple(p_t, mytag) );
264 expression_coeff.insert( std::make_pair(term.coeff, value_type()) );
265 expression_terms.push_back(term);
280 return symm_basis[type].phys_dim();
285 return init_charge<SymmGroup>(parms_, all_conserved_qn);
300 if (name ==
"id" || name ==
"ident" || name ==
"identity") {
304 if (match == operators.end()) {
305 SiteOperator op = make_site_term(name, parms);
306 match = register_operator(op, type, parms);
308 return match->second;
318 boost::ptr_vector<measurement<Matrix, SymmGroup> >
measurements ()
const;
322 template <
class SiteOp>
323 std::string simplify_name(
const SiteOp &op)
const
325 std::string term = op.term();
326 std::string arg =
"("+op.site()+
")";
327 boost::algorithm::replace_all(term,arg,
"");
331 bool fermionic (alps::SiteBasisDescriptor<I>
const& b1, SiteOperator
const& op1,
332 alps::SiteBasisDescriptor<I>
const& b2, SiteOperator
const& op2)
const
334 return b1.is_fermionic(simplify_name(op1)) && b2.is_fermionic(simplify_name(op2));
337 inline op_t convert_matrix (
const alps_matrix& m,
int type)
const
340 for (
int i=0; i<m.shape()[0]; ++i) {
341 for (
int j=0; j<m.shape()[1]; ++j) {
343 charge c_i = symm_basis[type].charge(i);
344 size_t bsize_i = symm_basis[type].block_size(i);
345 charge c_j = symm_basis[type].charge(j);
346 size_t bsize_j = symm_basis[type].block_size(j);
348 if (!newm.has_block(c_i, c_j))
349 newm.insert_block(Matrix(bsize_i, bsize_j, 0), c_i, c_j);
351 newm(symm_basis[type].coords(i), symm_basis[type].coords(j)) = m[i][j];
358 alps::SiteOperator make_site_term(std::string x, alps::Parameters
const & parms)
const
360 if (x[x.size()-1]!=
')')
362 alps::SiteOperator op(x,
"i");
363 model.substitute_operators(op, parms);
367 opmap_const_iterator register_operator(SiteOperator
const& op,
int type, alps::Parameters
const& p)
const
369 alps::SiteBasisDescriptor<I>
const& b = basis_descriptors[type];
370 alps_matrix m = alps::get_matrix(value_type(), op, b, p,
true);
372 tag_type mytag = tag_handler->register_op(convert_matrix(m, type), kind);
375 boost::tie(match, boost::tuples::ignore) = operators.insert( std::make_pair(
opkey_type(simplify_name(op), type), mytag) );
379 std::pair<meas_operators_type, short> operators_for_meas(std::string
const& ops,
bool repeat_one=
false)
const
383 int ntypes = alps::maximum_vertex_type(lattice.graph())+1;
386 boost::char_separator<char> sep(
":");
387 tokenizer corr_tokens(ops, sep);
388 std::vector<std::string> opnames;
391 for (tokenizer::iterator it=corr_tokens.begin(); it != corr_tokens.end(); it++)
393 if (model.has_bond_operator(*it)) {
395 BondOperator bondop = model.get_bond_operator(*it);
397 typedef std::vector<boost::tuple<alps::expression::Term<value_type>,alps::SiteOperator,alps::SiteOperator > > V;
399 alps::SiteBasisDescriptor<I>
const& b1 = basis_descriptors[0];
400 alps::SiteBasisDescriptor<I>
const& b2 = basis_descriptors[0];
402 V bond_terms = bondop.template templated_split<value_type>(b1,b2);
403 if (std::distance(bond_terms.begin(), bond_terms.end()) != 1)
throw std::runtime_error(
"Can only measure BONDOPERATOR with a single term.");
405 SiteOperator op1 = boost::get<1>(*bond_terms.begin());
406 SiteOperator op2 = boost::get<2>(*bond_terms.begin());
408 opnames.push_back(simplify_name(op1));
409 opnames.push_back(simplify_name(op2));
412 opnames.push_back(*it);
417 if (op_types == 3)
throw std::runtime_error(
"Can only have either site operators or bond operators.");
421 for (std::vector<std::string>::const_iterator it2 = opnames.begin(); it2 != opnames.end(); ++it2)
423 enum {uknown,
bosonic, fermionic} kind = uknown;
424 std::vector<op_t> tops(ntypes);
425 for (
int type=0; type<ntypes; ++type) {
426 alps::SiteBasisDescriptor<I>
const& b = basis_descriptors[type];
427 if (b.has_operator(*it2)) {
428 SiteOperator op = make_site_term(*it2, parms);
429 bool is_ferm = b.is_fermionic(simplify_name(op));
431 kind = is_ferm ? fermionic :
bosonic;
432 else if ((is_ferm && kind==
bosonic) || (!is_ferm && kind==fermionic))
433 throw std::runtime_error(
"Model is inconsitent. On some site the operator " + *it2 +
"fermionic, on others is bosonic.");
438 if (kind == fermionic) ++f_ops;
439 ret.push_back( std::make_pair(tops, (kind==fermionic)) );
443 if (repeat_one && op_types == 1 && ret.size() == 1) {
444 ret.push_back(ret[0]);
445 if (ret[1].second) ++f_ops;
448 if (repeat_one && op_types == 2 && ret.size() == 2) {
449 ret.push_back(ret[0]);
450 ret.push_back(ret[1]);
451 if (ret[2].second) ++f_ops;
452 if (ret[3].second) ++f_ops;
456 throw std::runtime_error(
"Number of fermionic operators has to be even.");
458 return std::make_pair(ret, op_types);
461 void generate_terms()
464 this->
terms_.reserve(expression_terms.size());
466 alps::Parameters parms_with_defaults(parms);
467 parms_with_defaults.copy_undefined(model.model().default_parameters());
469 typedef typename boost::container::flat_map<expression_type, value_type>::iterator coeff_iterator;
470 for(coeff_iterator it = expression_coeff.begin(); it != expression_coeff.end(); ++it)
471 it->second = alps::evaluate<value_type>(it->first, parms_with_defaults);
473 typedef typename std::vector<expression_term>::const_iterator terms_iterator;
474 for(terms_iterator it = expression_terms.begin(); it != expression_terms.end(); ++it) {
475 value_type
const& val = expression_coeff[it->coeff];
476 if ( alps::numeric::is_nonzero(val) ) {
478 term.is_fermionic = it->is_fermionic;
479 term.insert(term.end(), it->begin(), it->end());
481 this->
terms_.push_back(term);
487 alps::Parameters parms;
489 graph_type
const& lattice;
490 alps::model_helper<I> model;
493 std::set<std::string> all_qn;
494 qn_map_type all_conserved_qn;
495 std::vector<symmetric_basis_descriptor<SymmGroup> > symm_basis;
496 std::vector<alps::SiteBasisDescriptor<I> > basis_descriptors;
497 std::vector<alps::site_basis<I> > site_bases;
500 std::vector<expression_term> expression_terms;
501 boost::container::flat_map<expression_type, value_type> expression_coeff;
505 template <
class Matrix,
class SymmGroup>
508 if ( p_[
"init_state"] ==
"local_quantumnumbers" ) {
509 int max_site_type = 0;
510 std::vector<int> site_types(lat.
size(), 0);
511 for (
int p = 0; p < lat.
size(); ++p) {
512 site_types[p] = lat.
get_prop<
int>(
"type", p);
513 max_site_type = std::max(site_types[p], max_site_type);
516 std::cout <<
"site_types: ";
517 std::copy(site_types.begin(), site_types.end(), std::ostream_iterator<int>(std::cout,
" "));
518 std::cout << std::endl;
520 std::vector<Index<SymmGroup> > phys_bases(symm_basis.size());
521 for (
int type = 0; type < phys_bases.size(); ++type) {
522 phys_bases[type] = symm_basis[type].phys_dim();
523 maquis::cout <<
"phys["<< type <<
"]: " << phys_bases[type] << std::endl;
527 std::map<std::string, std::vector<double> > initial_local_charges;
528 for(std::set<std::string>::const_iterator it = all_qn.begin(); it != all_qn.end(); ++it) {
529 const std::string pname =
"initial_local_" + *it;
530 if (!p_.defined(pname))
531 throw std::runtime_error(pname +
" required for local_quantumnumbers initial state.");
532 initial_local_charges[*it] = p_[pname].as<std::vector<double> >();
535 std::vector<boost::tuple<charge, size_t> > state(lat.
size());
536 for (
size_t p=0; p<lat.
size(); ++p) {
537 const int type = site_types[p];
538 alps::SiteBasisDescriptor<I>
const& b = basis_descriptors[type];
539 alps::site_state<I> local_state;
540 for (
size_t i=0; i<b.size(); ++i)
541 local_state.push_back( initial_local_charges[b[i].name()][p] );
542 state[p] = symm_basis[type].coords(site_bases[type].index(local_state));
547 return base::initializer(lat, p_);
553 template <
class Matrix,
class SymmGroup>
554 boost::ptr_vector<measurement<Matrix, SymmGroup> >
557 boost::ptr_vector<measurement<Matrix, SymmGroup> > meas;
559 int ntypes = alps::maximum_vertex_type(lattice.graph())+1;
561 std::vector<op_t> identitities(ntypes), fillings(ntypes);
562 for (
int type=0; type<ntypes; ++type) {
564 fillings[type] = this->filling_matrix(type);
568 boost::regex average_expr(
"^MEASURE_AVERAGE\\[(.*)]$");
569 boost::regex locale_expr(
"^MEASURE_LOCAL\\[(.*)]$");
571 for (alps::Parameters::const_iterator it=parms.begin();it != parms.end();++it) {
572 std::string lhs = it->key();
575 enum {not_found, is_local, is_average} meas_found = not_found;
576 if (boost::regex_match(lhs, what, average_expr)) {
577 meas_found = is_average;
578 obsname = what.str(1);
580 if (boost::regex_match(lhs, what, locale_expr)) {
581 meas_found = is_local;
582 obsname = what.str(1);
585 if (meas_found != not_found) {
587 if (model.has_bond_operator(it->value())) {
588 BondOperator bondop = model.get_bond_operator(it->value());
590 typedef std::vector<op_t> op_vec;
591 typedef std::vector<std::pair<op_vec, bool> > bond_element;
592 typedef std::vector<boost::tuple<alps::expression::Term<value_type>,alps::SiteOperator,alps::SiteOperator > > V;
594 std::vector<op_t> tops1(ntypes), tops2(ntypes);
596 std::vector<bond_element> operators;
597 std::set<int> used1, used2;
598 for (
int type1=0; type1<ntypes; ++type1)
599 for (
int type2=0; type2<ntypes; ++type2) {
600 if (used1.find(type1) != used1.end() && used2.find(type2) != used2.end())
603 alps::SiteBasisDescriptor<I>
const& b1 = basis_descriptors[type1];
604 alps::SiteBasisDescriptor<I>
const& b2 = basis_descriptors[type2];
606 V ops = bondop.template templated_split<value_type>(b1,b2);
607 if (operators.size() < ops.size()) operators.resize(ops.size(), bond_element(2, std::make_pair(op_vec(ntypes),
false)) );
609 for (
typename V::iterator tit=ops.begin(); tit!=ops.end();++tit) {
610 SiteOperator op1 = boost::get<1>(*tit);
611 SiteOperator op2 = boost::get<2>(*tit);
613 if (!b1.has_operator(simplify_name(op1)) || !b2.has_operator(simplify_name(op2)))
616 unsigned ii = std::distance(ops.begin(), tit);
618 operators[ii][0].second = b1.is_fermionic(simplify_name(op1));
619 op_t & m = operators[ii][0].first[type1];
620 if (operators[ii][0].second)
621 gemm(fillings[type1], this->get_operator(simplify_name(op1), type1), m);
623 m = this->get_operator(simplify_name(op1), type1);
624 m = boost::get<0>(*tit).value() * m;
627 operators[ii][1].second = b2.is_fermionic(simplify_name(op2));
628 op_t & m = operators[ii][1].first[type2];
629 m = this->get_operator(simplify_name(op2), type2);
635 if (num_done == ops.size()) { used1.insert(type1); used2.insert(type2); }
638 if (meas_found == is_average)
643 std::vector<op_t> tops(ntypes);
644 for (
int type=0; type<ntypes; ++type) {
645 alps::SiteBasisDescriptor<I>
const& b = basis_descriptors[type];
646 if (b.has_operator(it->value())) {
647 SiteOperator op = make_site_term(it->value(), parms);
648 if (b.is_fermionic(simplify_name(op)))
649 throw std::runtime_error(
"Cannot measure local fermionic operators.");
651 tops[type] = this->get_operator(it->value(), type);
654 if (meas_found == is_average)
664 boost::regex expression(
"^MEASURE_LOCAL_AT\\[(.*)]$");
666 for (alps::Parameters::const_iterator it=parms.begin();it != parms.end();++it) {
667 std::string lhs = it->key();
668 std::string value = it->value();
669 if (boost::regex_match(lhs, what, expression)) {
672 std::string name = what.str(1);
674 boost::char_separator<char> part_sep(
"|");
675 tokenizer part_tokens(value, part_sep);
676 std::vector<std::string> parts;
677 std::copy( part_tokens.begin(), part_tokens.end(), std::back_inserter(parts) );
679 if (parts.size() != 2)
680 throw std::runtime_error(
"MEASURE_LOCAL_AT must contain a `|` delimiter.");
684 boost::tie(operators, boost::tuples::ignore) = operators_for_meas(parts[0],
false);
687 std::vector<std::vector<std::size_t> > positions;
688 boost::regex pos_re(
"\\(([^(^)]*)\\)");
689 boost::sregex_token_iterator it_pos(parts[1].begin(), parts[1].end(), pos_re, 1);
690 boost::sregex_token_iterator it_pos_end;
691 for (; it_pos != it_pos_end; ++it_pos)
693 boost::char_separator<char> int_sep(
", ");
694 std::string raw = *it_pos;
695 tokenizer int_tokens(raw, int_sep);
697 std::vector<std::size_t> pos;
698 BOOST_FOREACH(std::string t, int_tokens) {
699 pos.push_back(boost::lexical_cast<std::size_t, std::string>(t));
701 positions.push_back(pos);
704 throw std::runtime_error(
"Number of fermionic operators has to be even.");
712 boost::regex expression(
"^MEASURE_MPS_BONDS\\[(.*)]$");
714 for (alps::Parameters::const_iterator it=parms.begin();it != parms.end();++it) {
715 std::string lhs = it->key();
718 if (boost::regex_match(lhs, what, expression)) {
719 throw std::runtime_error(
"MEASURE_MPS_BONDS not yet implemented in new version.");
731 boost::regex expression(
"^MEASURE_CORRELATIONS\\[(.*)]$");
732 boost::regex expression_half(
"^MEASURE_HALF_CORRELATIONS\\[(.*)]$");
733 boost::regex expression_nn(
"^MEASURE_NN_CORRELATIONS\\[(.*)]$");
734 boost::regex expression_halfnn(
"^MEASURE_HALF_NN_CORRELATIONS\\[(.*)]$");
736 for (alps::Parameters::const_iterator it=parms.begin();it != parms.end();++it) {
737 std::string lhs = it->key();
739 std::string name, value;
740 bool half_only=
true, nearest_neighbors_only=
false;
741 if (boost::regex_match(lhs, what, expression)) {
745 nearest_neighbors_only =
false;
747 if (boost::regex_match(lhs, what, expression_half)) {
751 nearest_neighbors_only =
false;
753 if (boost::regex_match(lhs, what, expression_nn)) {
757 nearest_neighbors_only =
true;
759 if (boost::regex_match(lhs, what, expression_halfnn)) {
763 nearest_neighbors_only =
true;
767 std::vector<std::string> value_split;
768 boost::split( value_split, value, boost::is_any_of(
"@"));
772 boost::tie(operators, ops_type) = operators_for_meas(value_split[0],
true);
774 if (ops_type == 2) nearest_neighbors_only =
true;
777 std::vector<std::size_t> positions;
778 if (value_split.size() > 1) {
779 boost::char_separator<char> pos_sep(
", ");
780 tokenizer pos_tokens(value_split[1], pos_sep);
781 BOOST_FOREACH(std::string t, pos_tokens) {
782 positions.push_back(boost::lexical_cast<std::size_t, std::string>(t));
787 half_only, nearest_neighbors_only,
virtual op_t const & get_operator(std::string const &name, size_t type) const
boost::ptr_vector< measurement< Matrix, SymmGroup > > measurements_type
alps::graph_helper const & get_graph(Lattice const &lat_)
table_ptr operators_table() const
boost::ptr_vector< measurement< Matrix, SymmGroup > > measurements() const
definition of Model base class
::term_descriptor< expression_type > expression_term
base::table_type table_type
block_matrix< Matrix, SymmGroup > identity_matrix(Index< SymmGroup > const &size)
size_type insert_block(Matrix const &, charge, charge)
tag_type identity_matrix_tag(size_t type) const
boost::shared_ptr< table_type > table_ptr
SymmGroup::charge total_quantum_numbers(BaseParameters &parms_) const
initializer_ptr initializer(Lattice const &lat, BaseParameters &p_) const
table_type::tag_type tag_type
std::vector< term_descriptor > terms_type
std::pair< std::string, int > opkey_type
ALPSModel(Lattice const &lattice_, const alps::Parameters &parms_)
base::terms_type terms_type
std::map< opkey_type, tag_type > opmap_type
tag_type get_operator_tag(std::string const &name, size_t type) const
Index< SymmGroup > const & phys_dim(size_t type) const
void update(BaseParameters const &p)
std::size_t locale_shared
base::term_descriptor value_term
opmap_type::const_iterator opmap_const_iterator
base::initializer_ptr initializer_ptr
const graph_type & alps_graph() const
T get_prop(std::string property, pos_t site) const
::term_descriptor< typename Matrix::value_type > term_descriptor
bool has_block(charge r, charge c) const
alps::expression::Term< value_type > expression_type
base::table_ptr table_ptr
std::vector< std::pair< std::vector< op_t >, bool > > meas_operators_type
void gemm(block_matrix< Matrix1, SymmGroup > const &A, block_matrix< Matrix2, SymmGroup > const &B, block_matrix< Matrix3, SymmGroup > &C)
boost::shared_ptr< mps_initializer< Matrix, SymmGroup > > initializer_ptr
tag_type filling_matrix_tag(size_t type) const
base::measurements_type measurements_type