/*******************************************************************************
*
* TRIQS: a Toolbox for Research in Interacting Quantum Systems
*
* Copyright (C) 2012-2014 by M. Ferrero, O. Parcollet
*
* TRIQS is free software: you can redistribute it and/or modify it under the
* terms of the GNU General Public License as published by the Free Software
* Foundation, either version 3 of the License, or (at your option) any later
* version.
*
* TRIQS is distributed in the hope that it will be useful, but WITHOUT ANY
* WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
* FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
* details.
*
* You should have received a copy of the GNU General Public License along with
* TRIQS. If not, see .
*
******************************************************************************/
#pragma once
#include
#include
#include
#include
#include
namespace triqs {
namespace gfs {
using dcomplex = std::complex;
using arrays::array;
using arrays::array_view;
using arrays::matrix_view;
using arrays::matrix;
using arrays::make_shape;
using arrays::range;
using arrays::ellipsis;
using arrays::mini_vector;
class tail; // the value class
class tail_view; // the view class
class tail_const_view; // the const view class
// ---------------------- implementation --------------------------------
enum rvc_enum {
Regular,
View,
ConstView
};
template struct __get_rvc;
template using get_rvc = typename __get_rvc::type;
template struct __get_rvc {
using type = T;
};
template struct __get_rvc {
using type = typename T::view_type;
};
template struct __get_rvc {
using type = typename T::const_view_type;
};
/// A common implementation class.
template class tail_impl {
public:
TRIQS_MPI_IMPLEMENTED_VIA_BOOST;
using view_type = tail_view;
using const_view_type = tail_view;
using regular_type = tail;
using data_type = get_rvc>;
using mask_type = get_rvc>;
using mv_type = matrix_view;
using const_mv_type = matrix_view;
data_type & data() { return _data; }
data_type const & data() const { return _data; }
mask_type & mask() { return _mask; }
mask_type const & mask() const { return _mask; }
int order_min() const { return omin; }
int order_max() const { return min_element(_mask); }
size_t size() const { return _data.shape()[0]; }
int smallest_nonzero() const {
int om = omin;
while ((om < order_max()) && (max_element(abs(_data(om - omin, ellipsis()))) < 1.e-10)) om++;
return om;
}
using shape_type = mini_vector;
shape_type shape() const { return shape_type(_data.shape()[1], _data.shape()[2]); }
bool is_decreasing_at_infinity() const { return (smallest_nonzero() >= 1); }
protected:
int omin = -1;
mask_type _mask;
data_type _data;
tail_impl() = default;
tail_impl(int N1, int N2, int size_, int order_min)
: omin(order_min), _mask(arrays::make_shape(N1, N2)), _data(make_shape(size_, N1, N2)) {
_mask() = order_min + size_ - 1;
_data() = 0;
}
tail_impl(data_type const &d, mask_type const &m, int omin_) : omin(omin_), _mask(m), _data(d) {}
template tail_impl(tail_impl const &x) : omin(x.order_min()), _mask(x.mask()), _data(x.data()) {}
friend class tail;
friend class tail_view;
friend class tail_const_view;
friend tail compose(tail_const_view x, tail_const_view omega);
// operator = for views
void operator=(tail_const_view const &rhs); // implemented later
public:
mv_type operator()(int n) {
if (n > order_max()) TRIQS_RUNTIME_ERROR << " n > Max Order. n= " << n << ", Max Order = " << order_max();
if (n < order_min()) TRIQS_RUNTIME_ERROR << " n < Min Order. n= " << n << ", Min Order = " << order_min();
return _data(n - omin, ellipsis());
}
const_mv_type operator()(int n) const {
if (n > order_max()) TRIQS_RUNTIME_ERROR << " n > Max Order. n= " << n << ", Max Order = " << order_max();
if (n < order_min()) {
mv_type::regular_type r(shape());
r() = 0;
return r;
}
return _data(n - omin, ellipsis());
}
/// same as (), but if n is too large, then returns 0 instead of raising an exception
const_mv_type get_or_zero(int n) const {
if ((n > order_max()) || (n < order_min())) {
mv_type::regular_type r(shape());
r() = 0;
return r;
}
return _data(n - omin, ellipsis());
}
friend std::string get_triqs_hdf5_data_scheme(tail_impl const &g) { return "TailGf"; }
///
friend void h5_write(h5::group fg, std::string subgroup_name, tail_impl const &t) {
auto gr = fg.create_group(subgroup_name);
h5_write(gr, "omin", t.omin);
h5_write(gr, "mask", t._mask);
h5_write(gr, "data", t._data);
}
friend void h5_read(h5::group fg, std::string subgroup_name, tail_impl &t) {
auto gr = fg.open_group(subgroup_name);
h5_read(gr, "omin", t.omin);
h5_read(gr, "mask", t._mask);
h5_read(gr, "data", t._data);
}
// BOOST Serialization
friend class boost::serialization::access;
template void serialize(Archive &ar, const unsigned int version) {
ar &TRIQS_MAKE_NVP("omin", omin);
ar &TRIQS_MAKE_NVP("mask", _mask);
ar &TRIQS_MAKE_NVP("data", _data);
}
};
// -----------------------------
class tail_const_view : public tail_impl {
using B = tail_impl;
// friend class tail;
public:
tail_const_view(B::data_type d, B::mask_type m, int order_min) : B(std::move(d), std::move(m), order_min) {}
tail_const_view(tail_const_view const &) = default;
tail_const_view(tail_const_view &&) = default;
tail_const_view(tail_impl const &t) : B(t) {}
tail_const_view(tail_impl const &t) : B(t) {}
void rebind(tail_const_view const &X);
};
// -----------------------------
class tail_view : public tail_impl {
using B = tail_impl;
// friend class tail;
public:
tail_view(B::data_type d, B::mask_type m, int order_min) : B(std::move(d), std::move(m), order_min) {}
tail_view(tail_view const &) = default;
tail_view(tail_view &&) = default;
tail_view(tail_impl const &t) : B(t) {}
void rebind(tail_view const &X);
tail_view &operator=(tail_view const &x) { return B::operator=(tail_const_view(x)), *this; }
template tail_view &operator=(tail_impl const &x) { return B::operator=(tail_const_view(x)), *this; }
tail_view &operator=(dcomplex);
};
// -----------------------------
// the regular class
class tail : public tail_impl {
using B = tail_impl;
// friend class tail_view;
public:
using shape_type = mini_vector;
tail() = default;
tail(int N1, int N2, int size_ = 10, int order_min = -1) : B(N1, N2, size_, order_min) {}
tail(shape_type const &sh, int size_ = 10, int order_min = -1) : B(sh[0], sh[1], size_, order_min) {}
tail(mini_vector) : tail(1, 1) {}
tail(B::data_type const &d, B::mask_type const &m, int order_min) : B(d, m, order_min) {}
tail(tail const &g) : B(g) {}
tail(tail_view const &g) : B(g) {}
tail(tail_const_view const &g) : B(g) {}
tail(tail &&) = default;
tail &operator=(tail const &x) { return B::operator=(tail_const_view(x)), *this; }
template tail &operator=(tail_impl const &x) { return B::operator=(tail_const_view(x)), *this; }
};
// ---- impl. of = for base class -------------
template void tail_impl::operator=(tail_const_view const &rhs) {
if (RVC == Regular) {
omin = rhs.order_min();
} else {
if ((_data.shape()[1] != rhs.data().shape()[1]) || (_data.shape()[2] != rhs.data().shape()[2]) || (omin != rhs.order_min()))
TRIQS_RUNTIME_ERROR << "tails are incompatible";
}
_mask = rhs.mask();
_data = rhs.data();
}
// ---- Factories -------------
/// The simplest tail corresponding to omega
tail tail_omega(int N1, int N2, int size_ = 10, int order_min = -1);
/// The simplest tail corresponding to omega, constructed from a shape for convenience
tail_view tail_omega(tail::shape_type const &sh, int size_, int order_min);
/// The simplest tail corresponding to omega, built from the shape, size, ordermin of t
tail_view tail_omega(tail_view t);
// ---- IO -------------
std::ostream &operator<<(std::ostream &out, tail_const_view);
// ---- -------------
//
template void assign_singularity_from_function(tail_view t, RHS const &rhs) {
t = rhs(tail_omega(t.shape(), t.size(), t.order_min()));
}
// ---- Evaluate and compose -------------
/// Evaluate the tail to sum_{n=order_min}^ordermax M_n/omega^n
matrix evaluate(tail_const_view t, dcomplex const &omega);
tail compose(tail_const_view x, tail_const_view t);
// ---- Ops -------------
tail conj(tail_const_view const &t);
tail transpose(tail_const_view const &t);
/// Slice in orbital space
tail_const_view slice_target(tail_const_view const &t, range R1, range R2);
tail_view slice_target(tail_view t, range R1, range R2);
inline tail_view slice_target(tail &t, range R1, range R2) { return slice_target(tail_view{t}, R1, R2);}
inline tail_const_view slice_target(tail const &t, range R1, range R2) { return slice_target(tail_const_view{t}, R1, R2);}
tail inverse(tail_const_view const &t);
/// ------------------- Arithmetic operations ------------------------------
tail operator+(tail_const_view const &l, tail_const_view const &r);
tail operator-(tail_const_view const &l, tail_const_view const &r);
// +/- with scalar or matrix.
template
struct is_scalar_or_matrix : std::integral_constant>::value || utility::is_in_ZRC::value> {};
template std14::enable_if_t::value, tail> operator+(T const &a, tail_const_view const &t) {
tail res(t);
res(0) += a;
return res;
}
template std14::enable_if_t::value, tail> operator+(tail_const_view const &t, T const &a) {
return a + t;
}
template std14::enable_if_t::value, tail> operator-(T const &a, tail_const_view const &t) {
return (-a) + t;
}
template std14::enable_if_t::value, tail> operator-(tail_const_view const &t, T const &a) {
return (-a) + t;
}
tail operator*(tail_const_view const &l, tail_const_view const &r);
tail operator*(matrix const &a, tail_const_view const &b);
tail operator*(tail_const_view const &a, matrix const &b);
template tail operator*(matrix_view const &a, tail_const_view const &b) { return matrix(a) * b; }
template tail operator*(tail_const_view const &a, matrix_view const &b) { return a * matrix(b); }
tail operator*(dcomplex a, tail_const_view const &r);
inline tail operator*(tail_const_view const &r, dcomplex a) { return a * r; }
inline tail operator/(tail_const_view const &a, tail_const_view const &b) { return a * inverse(b); }
tail operator/(tail_const_view const &r, dcomplex a);
inline tail operator/(dcomplex a, tail_view r) { return a * inverse(r); }
// inplace operators
#define DEFINE_OPERATOR(OP1, OP2) \
template void operator OP1(tail_view g, T &&x) { g = g OP2 x; } \
template void operator OP1(tail &g, T &&x) { g = g OP2 x; }
DEFINE_OPERATOR(+=, +);
DEFINE_OPERATOR(-=, -);
DEFINE_OPERATOR(*=, *);
DEFINE_OPERATOR(/=, / );
#undef DEFINE_OPERATOR
}
}