14 #include <boost/preprocessor/cat.hpp> 15 #include <boost/preprocessor/repetition/repeat_from_to.hpp> 35 template<
class VTYPE,
class Storage,
class ...MESHES>
38 template <
typename Tuple, std::size_t...Is>
39 std::ostream & output(std::ostream & os,
const Tuple& t, index_sequence<Is...>) {
40 using swallow =
int[];
41 (void)swallow{0, (void(os << std::get<Is>(t)), 0)...};
45 template <
typename ...Args>
46 auto operator<<(std::ostream & os,
const std::tuple<Args...>& t) ->
49 template<typename T> inline
void print_no_complex(
std::ostream &os, const T &z){
52 template<>
inline void print_no_complex(std::ostream &os,
const std::complex<double> &z){
54 os<<z.real()<<
" "<<z.imag();
61 template<
class VTYPE,
class ...MESHES>
66 template<class VTYPE, class ...MESHES>
73 template<
class VTYPE,
class Storage,
class ...MESHES>
79 using value_type = VTYPE;
81 using storage_type = Storage;
83 using mesh_types = std::tuple < MESHES... >;
85 using index_types = std::tuple <
typename MESHES::index_type... >;
88 using gf_type = gf_base < VTYPE, Storage, MESHES... >;
94 using generic_gf = gf_base < VTYPE, St, MESHES... >;
96 template<
typename RHS_VTYPE>
97 using gf_op_type = gf_base < decltype(RHS_VTYPE{} + VTYPE{}),
numerics::tensor<decltype(RHS_VTYPE{} + VTYPE{}),
98 sizeof...(MESHES)>, MESHES... >;
103 static constexpr
int minor_version = 1;
104 static constexpr
int major_version = 0;
106 static constexpr
int N_ =
sizeof...(MESHES);
110 std::tuple < MESHES... > meshes_;
121 template <
typename S,
class Tup>
struct subpack_impl;
122 template<
typename S,
template<
class...>
class Tup,
class... T>
123 struct subpack_impl<S, Tup<T...> >
127 template<
typename S,
size_t I>
128 using subpack =
typename subpack_impl<S, decltype(tuple_tail < I, MESHES... >(meshes_) )>::type;
130 template<
typename RHS_VTYPE,
typename LHS_VTYPE>
132 typedef typename std::conditional<std::is_integral<RHS_VTYPE>::value, VTYPE, RHS_VTYPE>::type type;
140 template<
typename ...IndicesTypes>
142 using type =
typename std::conditional<std::is_convertible<std::tuple<IndicesTypes...>, index_types>::value,
143 std::true_type, std::false_type>::type;
152 gf_base(
const gf_type &g) =
default;
157 gf_base(gf_type &&g) =
default;
162 gf_base() : data_(std::array < size_t, N_ >{{0}}), empty_(
true) {}
168 gf_base(MESHES...meshes) : gf_base(std::make_tuple(meshes...)) {}
173 gf_base(
const mesh_types &meshes) : data_(get_sizes(meshes)), meshes_(meshes), empty_(
false) {}
175 gf_base(VTYPE* data,
const mesh_types &meshes) : data_(data, get_sizes(meshes)), meshes_(meshes), empty_(
false) {}
177 gf_base(
const data_storage &data,
const mesh_types &meshes) : data_(data), meshes_(meshes), empty_(
false) {}
179 gf_base(data_storage &&data,
const mesh_types &meshes) : data_(data), meshes_(meshes), empty_(
false) {}
181 gf_base(
const data_storage &data, MESHES...meshes) : data_(data), meshes_(std::make_tuple(meshes...)), empty_(
false) {}
183 gf_base(data_storage && data, MESHES...meshes) : data_(std::move(data)), meshes_(std::make_tuple(meshes...)), empty_(
false) {}
186 template<typename St, typename = std::enable_if<!std::is_same<St, Storage>::value && std::is_same<St, data_view>::value > >
187 gf_base(
const gf_base<VTYPE, St, MESHES...> &g) : data_(g.data()), meshes_(g.meshes()), empty_(g.is_empty()) {}
188 template<typename St, typename = std::enable_if<!std::is_same<St, Storage>::value && std::is_same<St, data_storage>::value > >
189 gf_base(gf_base<VTYPE, St, MESHES...> &g) : data_(g.data()), meshes_(g.meshes()), empty_(g.is_empty()) {}
192 template<typename RHS_VTYPE, typename St, typename = std::enable_if<std::is_same<data_storage, Storage>::value> >
193 gf_base(
const gf_base<RHS_VTYPE, St, MESHES...> &g) : data_(g.data()), meshes_(g.meshes()), empty_(g.is_empty()) {
194 static_assert(std::is_convertible<RHS_VTYPE, VTYPE>::value,
"Right-hand side data type is not convertible into left-hand side.");
196 template<typename RHS_VTYPE, typename St, typename = std::enable_if<std::is_same<data_storage, Storage>::value>>
197 gf_base(gf_base<RHS_VTYPE, St, MESHES...> &&g) noexcept : data_(std::move(g.data())), meshes_(std::move(g.meshes())), empty_(g.is_empty()) {
198 static_assert(std::is_convertible<RHS_VTYPE, VTYPE>::value,
"Right-hand side data type is not convertible into left-hand side.");
202 template<
typename St,
typename...OLDMESHES,
typename Index,
typename ...Indices>
203 gf_base(gf_base<VTYPE, numerics::detail::tensor_base < VTYPE,
sizeof...(OLDMESHES), St >, OLDMESHES...> & g,
204 std::tuple<OLDMESHES...>& oldmesh,
const mesh_types &meshes,
const Index ind,
const Indices... idx) :
205 data_(g.data()(ind(), idx()...)), meshes_(meshes), empty_(
false) {}
208 template<
typename RHSTYPE ,
typename St,
typename...OLDMESHES,
typename ...Indices>
209 gf_base(
const gf_base<RHSTYPE, numerics::detail::tensor_base < RHSTYPE,
sizeof...(OLDMESHES), St >, OLDMESHES...> & g,
210 const std::tuple<OLDMESHES...>& oldmesh, mesh_types &meshes,
const Indices... idx) :
211 data_(g.data()(idx()...)), meshes_(meshes), empty_(
false) {}
214 gf_type& operator=(
const gf_type & rhs) {
221 gf_type& operator=(gf_type && rhs) noexcept {
224 swap(data_, rhs.data_);
225 swap(empty_, rhs.empty_);
235 void check_meshes(
const gf_type& rhs)
const 237 if (meshes_ != rhs.meshes_) {
238 throw std::invalid_argument(
"Green Functions have incompatible meshes");
250 template<
class...Indices>
251 typename std::enable_if < (
sizeof...(Indices) ==
sizeof...(MESHES)),
const VTYPE & >::type
252 operator()(Indices...inds)
const {
254 static_assert(check_mesh<Indices...>::type::value,
"Index type is inconsistent with mesh index type.");
255 return value(std::forward < Indices >(inds)...);
259 template<
class...Indices>
260 typename std::enable_if < (
sizeof...(Indices) ==
sizeof...(MESHES)), VTYPE & >::type
261 operator()(Indices...inds) {
263 static_assert(check_mesh<Indices...>::type::value,
"Index type is inconsistent with mesh index type.");
264 return value(std::forward < Indices >(inds)...);
275 template<
class...Indices>
276 auto operator()(
typename std::enable_if<(
sizeof...(Indices)+1 < N_),
277 typename std::tuple_element<0,mesh_types>::type::index_type >::type ind, Indices...inds) ->
278 subpack<VTYPE,
sizeof...(Indices) + 1> {
279 return subpack<VTYPE,
sizeof...(Indices) + 1 >
280 (*
this, meshes_,
tuple_tail <
sizeof...(Indices) + 1, MESHES...>(meshes_), ind, std::forward<Indices>(inds)...);
283 template<
class...Indices>
284 auto operator()(
typename std::enable_if<(
sizeof...(Indices)+1 < N_),
285 typename std::tuple_element<0,mesh_types>::type::index_type >::type ind, Indices...inds)
const ->
286 subpack<
const VTYPE,
sizeof...(Indices) + 1> {
287 auto t =
tuple_tail <
sizeof...(Indices) + 1, MESHES...>(meshes_);
288 return subpack<
const VTYPE,
sizeof...(Indices) + 1> (*
this, meshes_, t, ind, std::forward<Indices>(inds)...);
303 template<
typename RHS_VTYPE,
typename RHS_STORAGE>
304 gf_op_type<RHS_VTYPE>
operator+(
const gf_base<RHS_VTYPE, RHS_STORAGE, MESHES...> &rhs)
const {
306 gf_op_type<RHS_VTYPE> res(*
this);
317 template<
typename RHS_GF>
318 typename std::enable_if < std::is_convertible < RHS_GF, generic_gf<data_storage>>::value ||
319 std::is_convertible < RHS_GF, generic_gf<data_view>>::value, gf_type & >::type
333 template<
typename RHS_VTYPE,
typename RHS_STORAGE>
334 gf_op_type<RHS_VTYPE>
operator-(
const gf_base<RHS_VTYPE, RHS_STORAGE, MESHES...> &rhs)
const {
336 gf_op_type<RHS_VTYPE> res(*
this);
343 template<
typename RHS_GF>
344 typename std::enable_if < std::is_convertible < RHS_GF, generic_gf<data_storage>>::value ||
345 std::is_convertible < RHS_GF, generic_gf<data_view>>::value, gf_type & >::type
359 template<
typename RHS>
360 typename std::enable_if < std::is_scalar < RHS >::value || std::is_same < VTYPE, RHS >::value, gf_type & >::type
operator*=(RHS rhs) {
373 template<
typename RHS>
374 gf_op_type<typename convert<RHS,VTYPE>::type>
operator*(RHS rhs)
const {
376 gf_op_type<typename convert<RHS,VTYPE>::type> res(*
this);
380 template<
typename LHS>
381 friend gf_op_type<typename convert<LHS,VTYPE>::type>
operator*(LHS lhs,
const gf_type & g) {
393 template<
typename RHS>
394 typename std::enable_if < std::is_scalar < RHS >::value || std::is_same < VTYPE, RHS >::value, gf_type & >::type
operator/=(RHS rhs) {
407 template<
typename RHS>
408 gf_op_type<typename convert<RHS,VTYPE>::type>
operator/(RHS rhs)
const {
410 gf_op_type<typename convert<RHS,VTYPE>::type> res(*
this);
414 template<
typename LHS>
415 friend gf_op_type<typename convert<LHS,VTYPE>::type>
operator/(LHS lhs,
const gf_type & g) {
422 gf_base < VTYPE, numerics::tensor<VTYPE, N_>, MESHES... >
operator-()
const {
424 return (*
this)*(VTYPE(-1.0));
434 template<
typename RHS_GF>
435 typename std::enable_if < std::is_convertible < RHS_GF, generic_gf<data_storage> >::value
436 || std::is_convertible < RHS_GF, generic_gf<data_view> >::value,
bool >::type
438 return (empty_ && rhs.is_empty()) || (data_.shape() == rhs.data().shape() && data_.storage() == rhs.data().storage() );
441 template<
typename RHS_GF>
443 return !(*
this==rhs);
449 double norm()
const {
451 return std::abs(*std::max_element(data_.data(), data_.num_elements() + data_.data(),
456 void reshape(MESHES...meshes) {
457 std::array<size_t, N_> new_shape = get_sizes(std::make_tuple(meshes...));
458 size_t new_size = std::accumulate(new_shape.begin(), new_shape.end(), size_t(1), std::multiplies<size_t>());
459 if(std::is_same<data_view, Storage>::value) {
460 if (data_.size() != new_size) {
461 throw std::invalid_argument(
"The total size of resulting Green's function view should be the same as before.");
464 data_.reshape(new_shape);
465 meshes_ = std::make_tuple(meshes...);
486 save_version(ar, path);
487 ar[path +
"/data"] << data_;
488 ar[path +
"/mesh/N"] << int(N_);
494 if (!check_version(ar, path))
throw std::runtime_error(
"Incompatible archive version");
496 ar[path +
"/mesh/N"] >> ndim;
497 if (ndim != N_)
throw std::runtime_error(
"Wrong number of dimension reading GF, ndim=" + std::to_string(ndim)
498 +
", should be N=" + std::to_string(N_));
501 ar[path +
"/data"] >> data_;
507 std::string vp = path +
"/version/";
508 ar[vp +
"minor"] << int(minor_version);
509 ar[vp +
"major"] << int(major_version);
510 ar[vp +
"reference"] <<
"https://github.com/ALPSCore/H5GF/blob/master/H5GF.rst";
511 ar[vp +
"originator"] <<
"ALPSCore GF library, see http://www.alpscore.org";
516 std::string vp = path +
"/version/";
518 ar[vp +
"major"] >> ver;
519 return (major_version == ver);
528 const Storage &data()
const {
return data_; };
532 Storage &data() {
return data_; };
537 bool is_empty()
const {
544 const mesh_types& meshes()
const {
return meshes_;}
558 if(comm.
rank() == root) throw_if_empty();
560 broadcast_mesh(comm, root);
561 size_t root_sz=data_.size();
580 bcast_mesh(comm, root, std::integral_constant < int, 0 >());
584 std::get<M>(meshes_).
broadcast(comm, root);
585 bcast_mesh(comm, root, std::integral_constant < int, M+1 >());
589 std::get<N_ - 1>(meshes_).
broadcast(comm, root);
596 inline void throw_if_empty()
const {
599 throw std::runtime_error(
"gf is empty");
611 template<
class ... Indices>
612 const VTYPE & value(Indices...inds)
const {
613 return data_(inds()...);
616 template<
class ... Indices>
617 VTYPE &value(Indices...inds) {
618 return data_(inds()...);
627 std::array < size_t, N_ > get_sizes(MESHES...meshes) {
628 return get_sizes(std::forward_as_tuple(meshes...));
637 std::array < size_t, N_ > get_sizes(
const mesh_types &meshes) {
638 std::array < size_t, N_ > sizes;
653 template<
size_t...Is>
655 return {{size_t(std::get<Is>(grids).extent())...}};
663 template<
size_t...Is>
665 std::tie(std::get < Is >(meshes_) = std::get < Is >(old_meshes)...);
675 template<
size_t...Is>
677 std::tie(ar[path +
"/mesh/" + std::to_string(Is+1)] << std::get < Is >(meshes_)...);
688 template<
size_t...Is>
690 std::tie(ar[path +
"/mesh/" + std::to_string(Is+1)] >> std::get < Is >(meshes_)...);
708 =
typename std::conditional < (i <= N_),
709 std::tuple_element < i - 1, mesh_types >,
710 void_type>::type::type;
718 #define MESH_FUNCTION(z, num, c) \ 719 template<typename = typename std::enable_if< (N_ >= num)> >\ 720 typename std::add_lvalue_reference<const typename args<num>::type>::type mesh##num() const {\ 721 return std::get<int(num-1)>(meshes_); \ 724 #define MESH_TYPES(z, num, c) \ 726 typedef typename args<num>::type mesh##num##_type; 733 BOOST_PP_REPEAT_FROM_TO (1, 11,
MESH_TYPES,
int)
738 friend
std::ostream &operator<<(
std::ostream &os, const gf_type & G ){
739 using detail::operator<<;
741 for(
int i=0;i<G.mesh1().extent();++i){
742 os<<(G.mesh1().points()[i])<<
" ";
743 size_t points = G.data().size()/G.data().shape()[0];
744 for(
size_t j = 0; j< points; ++j) {
745 detail::print_no_complex<value_type>(os, G.data().data()[j + G.data().index(i)]);
757 #endif //ALPSCORE_GF_H piecewise_polynomial< T > operator+(const piecewise_polynomial< T > &f1, const piecewise_polynomial< T > &f2)
Add piecewise_polynomial objects.
detail::gf_base< VTYPE, numerics::tensor_view< VTYPE, sizeof...(MESHES)>, MESHES... > greenf_view
void swap(matsubara_mesh< PTYPE > &a, matsubara_mesh< PTYPE > &b)
Swaps two Matsubara meshes.
make_integer_sequence< size_t, N > make_index_sequence
detail::tensor_base< T, D, detail::data_storage< T > > tensor
void load(archive &ar, std::string const &path, T &value, std::vector< std::size_t > chunk=std::vector< std::size_t >(), std::vector< std::size_t >=std::vector< std::size_t >())
boost::array< T, N > abs(boost::array< T, N > arg)
std::ostream & operator<<(std::ostream &os, const real_frequency_mesh &M)
void broadcast(C const &c, P &p, int r=0)
piecewise_polynomial< T > operator-(const piecewise_polynomial< T > &f1, const piecewise_polynomial< T > &f2)
Substract piecewise_polynomial objects.
const piecewise_polynomial< T > operator*(T scalar, const piecewise_polynomial< T > &pp)
Multiply piecewise_polynomial by a scalar.
void swap(params &p1, params &p2)
boost::array< T, N > operator/(boost::array< T, N > lhs, boost::array< U, N > const &rhs)
bool operator==(const dictionary &lhs, const dictionary &rhs)
auto tuple_tail(T &t) -> DECLTYPE(tuple_tail_< Trim >(t, make_index_sequence< Count-Trim >()))
Header for object-oriented interface to MPI (similar to boost::mpi)
Encapsulation of an MPI communicator and some communicator-related operations.
T norm(T x, T y=T(), T z=T())
boost::array< T, N > & operator+=(boost::array< T, N > &lhs, boost::array< T, N > const &rhs)
#define MESH_FUNCTION(z, num, c)
boost::array< T, N > & operator/=(boost::array< T, N > &lhs, boost::array< T, N > const &rhs)
detail::gf_base< VTYPE, numerics::tensor< VTYPE, sizeof...(MESHES)>, MESHES... > greenf
#define MESH_TYPES(z, num, c)
boost::array< T, N > & operator*=(boost::array< T, N > &lhs, boost::array< T, N > const &rhs)
std::string get_context() const
int rank() const
Returns process rank in this communicator.
void broadcast(const communicator &comm, T *vals, std::size_t count, int root)
Broadcasts array vals of a primitive type T, length count on communicator comm with root root ...
detail::tensor_base< T, D, detail::data_view< T > > tensor_view
bool operator!=(const dictionary &lhs, const dictionary &rhs)
boost::array< T, N > & operator-=(boost::array< T, N > &lhs, boost::array< T, N > const &rhs)
void save(archive &ar, std::string const &path, T const &value, std::vector< std::size_t >=std::vector< std::size_t >(), std::vector< std::size_t > chunk=std::vector< std::size_t >(), std::vector< std::size_t >=std::vector< std::size_t >())