Program Listing for File symmetry_group.hpp

Return to documentation for file (src_ed/symmetry_group.hpp)

#ifndef symmetry_group_h
#define symmetry_group_h

#include <iostream>
#include <vector>
#include <typeinfo>
#include <cstdint>

#include "qcm_ED.hpp"
#include "matrix.hpp"
#include "binary_state.hpp"
#include "sector.hpp"
#include "parser.hpp"
#include "index.hpp"
#include "symmetric_orbital.hpp"
#include "block_matrix.hpp"
#include "index_pair.hpp"

using namespace std;

#define MAX_GENERATORS 4

struct rep_map
{
  binary_state b;
  int phase;
  int length;
};


struct symmetry_group
{
  bool has_complex_irrep;
  bool bath_irrep;
  int N;
    int n_sites;
    int g;
  int L;
    vector<vector<int>> generator;
    vector<vector<int>> e;
    matrix<int> phi;
    matrix<Complex> chi;
    matrix<Complex> S;
  matrix<double> S_real;
  vector<bool> complex_irrep;
  vector<int> site_irrep_dim;
    vector<int> site_irrep_dim_cumul;
    matrix<int> tensor;
    vector<int> conjugate;
  vector<int> phaseR;
  vector<Complex> phaseC;


  symmetry_group(int _N, int _n_sites, const vector<vector<int>> &gen, bool bath_irrep);
  bool is_valid_element(const vector<int>& v, bool full=false);
  bool is_identity(const vector<int>& v, bool full=false);
  vector<int> product(const vector<int>& x, const vector<int>& y);
  vector<int> inverse(const vector<int>& x);
  vector<int> identity();
  int sign(const vector<int>& x);
  uint32_t apply_single(const vector<int>& x, const uint32_t b);
  pair<uint32_t, int> apply(const vector<int>& x, const uint32_t b);
  template<typename T>
  vector<T> apply_to_vector(const vector<int>& v, const vector<T>& x);
  pair<int, int> map_orbital(const vector<int>& v, int a);
  bool diff(const vector<int>& x, const vector<int>& y, bool full=false);
  void build();
  pair<binary_state, int> apply(const int &elem, const binary_state &b);
  pair<binary_state, int> apply(const int &elem, const int &irrep, const binary_state &b);
  rep_map Representative(const binary_state &b, int irrep);
  void to_site_basis(int r, vector<Complex> &x, vector<Complex> &y, int n_mixed);
  void to_site_basis(int r, vector<double> &x, vector<double> &y, int n_mixed);
  void to_site_basis(block_matrix<Complex> &B, matrix<Complex> &G, int n_mixed);
  bool sector_is_valid(const sector &sec);
  sector shift_sector(const sector &sec, int pm, int spin, int _irrep);
  bool operator!=(const symmetry_group &y);

  template<typename HilbertField>
  inline HilbertField phaseX(int i);

  template<typename HilbertField>
  void check_invariance(const map<index_pair,HilbertField> &elements, const string& name, bool interaction);
  vector<vector<symmetric_orbital>> build_symmetric_orbitals(int mixing);
};


std::ostream & operator<<(std::ostream &s, const symmetry_group &x);


// implementation


template<typename HilbertField>
void symmetry_group::check_invariance(const map<index_pair,HilbertField> &elements, const string& name, bool interaction)
{
  if(g==1) return;

  for(int i=0; i<generator.size(); i++){
    for(auto &x : elements){
      auto A = map_orbital(generator[i], x.first.r);
      A.second *= -1; // sign because c_a^\dg is a creation operator
      auto B = map_orbital(generator[i], x.first.c);
      int f = (A.second + B.second + 4*g)%(2*g); // positive modulo
      index_pair xp(A.first, B.first);
      auto y = elements.find(xp);
      if(y == elements.end() and interaction) y = elements.find(index_pair(B.first, A.first));
      if(y == elements.end()){
        ostringstream sout;
        sout << "Term " << x.first << " of parameter " << name << " is incompatible with symmetry generator " << i+1 << ", which maps it into " << xp;
        qcm_ED_throw(sout.str());
      }
      Complex ratio = x.second*phaseC[f]/y->second;
      if(abs(ratio-1.0) > 1e-8){
        ostringstream sout;
        sout << "Term " << x.first << " of parameter " << name << " is incompatible with symmetry generator " << i+1 << ", which maps it into " << xp << " but with value " << phaseC[f]*y->second << " instead of " << x.second;
        qcm_ED_throw(sout.str());
      }
    }
  }
}

template<>
inline double symmetry_group::phaseX<double>(int i){return phaseR[i];}

template<>
inline Complex symmetry_group::phaseX<Complex>(int i){return phaseC[i];}

#endif