2013-11-05 08:56:42 +01:00
|
|
|
/*******************************************************************************
|
|
|
|
*
|
|
|
|
* TRIQS: a Toolbox for Research in Interacting Quantum Systems
|
|
|
|
*
|
|
|
|
* Copyright (C) 2013 by 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 <http://www.gnu.org/licenses/>.
|
|
|
|
*
|
|
|
|
******************************************************************************/
|
|
|
|
#pragma once
|
|
|
|
#include "./mesh_tools.hpp"
|
|
|
|
#include "../domains/matsubara.hpp"
|
|
|
|
|
|
|
|
namespace triqs {
|
|
|
|
namespace gfs {
|
|
|
|
|
|
|
|
struct matsubara_freq_mesh {
|
|
|
|
|
2013-12-30 22:31:36 +01:00
|
|
|
///
|
2013-11-05 08:56:42 +01:00
|
|
|
using domain_t = matsubara_domain<true>;
|
2013-12-30 22:31:36 +01:00
|
|
|
///
|
|
|
|
using index_t = long;
|
|
|
|
///
|
2013-11-05 08:56:42 +01:00
|
|
|
using domain_pt_t = typename domain_t::point_t;
|
|
|
|
|
2013-12-30 22:31:36 +01:00
|
|
|
/// Constructor
|
2014-09-03 14:03:31 +02:00
|
|
|
matsubara_freq_mesh(domain_t dom, long n_pts = 1025, bool positive_only = true)
|
|
|
|
: _dom(std::move(dom)), _n_pts(n_pts), _positive_only(positive_only) {
|
|
|
|
if (_positive_only) {
|
|
|
|
_first_index = 0;
|
|
|
|
_last_index = n_pts - 1; // CORRECTION
|
|
|
|
} else {
|
|
|
|
_last_index = (_n_pts - (_dom.statistic == Boson ? 1 : 2)) / 2;
|
|
|
|
_first_index = -(_last_index + (_dom.statistic == Fermion));
|
|
|
|
}
|
|
|
|
_first_index_window = _first_index;
|
|
|
|
_last_index_window = _last_index;
|
|
|
|
}
|
2013-11-05 08:56:42 +01:00
|
|
|
|
2013-12-30 22:31:36 +01:00
|
|
|
/// Constructor
|
2014-09-03 14:03:31 +02:00
|
|
|
matsubara_freq_mesh() : matsubara_freq_mesh(domain_t(), 0, true){}
|
2013-11-05 08:56:42 +01:00
|
|
|
|
2013-12-30 22:31:36 +01:00
|
|
|
/// Constructor
|
2014-01-07 14:30:40 +01:00
|
|
|
matsubara_freq_mesh(double beta, statistic_enum S, int n_pts = 1025, bool positive_only = true)
|
|
|
|
: matsubara_freq_mesh({beta, S}, n_pts, positive_only) {}
|
2013-12-30 22:31:36 +01:00
|
|
|
|
|
|
|
/// Copy constructor
|
|
|
|
matsubara_freq_mesh(matsubara_freq_mesh const &) = default;
|
|
|
|
|
2014-09-03 14:03:31 +02:00
|
|
|
/// Scatter a mesh over the communicator c
|
|
|
|
friend matsubara_freq_mesh mpi_scatter(matsubara_freq_mesh m, mpi::communicator c, int root) {
|
|
|
|
auto m2 = matsubara_freq_mesh{m.domain(), m.size(), m.positive_only()};
|
|
|
|
std::tie(m2._first_index_window, m2._last_index_window) = mpi::slice_range(m2._first_index, m2._last_index, c.size(), c.rank());
|
|
|
|
return m2;
|
|
|
|
}
|
|
|
|
|
|
|
|
friend matsubara_freq_mesh mpi_gather(matsubara_freq_mesh m, mpi::communicator c, int root) {
|
|
|
|
return matsubara_freq_mesh{m.domain(), m.size(), m.positive_only()};
|
|
|
|
}
|
|
|
|
|
2013-12-30 22:31:36 +01:00
|
|
|
/// The corresponding domain
|
2013-11-05 08:56:42 +01:00
|
|
|
domain_t const &domain() const { return _dom; }
|
2013-12-30 22:31:36 +01:00
|
|
|
|
|
|
|
/** \brief First value of the index
|
|
|
|
*
|
|
|
|
* 0 if positive_only is true
|
|
|
|
* else :
|
2014-01-07 14:30:40 +01:00
|
|
|
* For fermions : -Nmax - 1
|
2013-12-30 22:31:36 +01:00
|
|
|
* For Bosons : -Nmax
|
2014-02-19 12:59:47 +01:00
|
|
|
**/
|
|
|
|
|
|
|
|
/// last Matsubara index
|
2014-09-03 14:03:31 +02:00
|
|
|
int last_index() const { return _last_index;}
|
2014-02-19 12:59:47 +01:00
|
|
|
|
|
|
|
/// first Matsubara index
|
2014-09-03 14:03:31 +02:00
|
|
|
int first_index() const { return _first_index;}
|
|
|
|
|
|
|
|
/// last Matsubara index of the window
|
|
|
|
int last_index_window() const { return _last_index_window;}
|
|
|
|
|
|
|
|
/// first Matsubara index of the window
|
|
|
|
int first_index_window() const { return _first_index_window;}
|
2013-11-05 08:56:42 +01:00
|
|
|
|
2013-12-30 22:31:36 +01:00
|
|
|
/// Size (linear) of the mesh
|
2014-09-03 14:03:31 +02:00
|
|
|
//long size() const { return _n_pts;}
|
|
|
|
|
|
|
|
/// Size (linear) of the mesh of the window
|
|
|
|
long size() const { return _last_index_window - _first_index_window + 1; }
|
2013-12-30 22:31:36 +01:00
|
|
|
|
|
|
|
/// From an index of a point in the mesh, returns the corresponding point in the domain
|
2014-01-05 16:56:41 +01:00
|
|
|
domain_pt_t index_to_point(index_t ind) const { return 1_j * M_PI * (2 * ind + (_dom.statistic == Fermion)) / _dom.beta; }
|
2013-11-05 08:56:42 +01:00
|
|
|
|
2013-12-30 22:31:36 +01:00
|
|
|
/// Flatten the index in the positive linear index for memory storage (almost trivial here).
|
2014-09-03 14:03:31 +02:00
|
|
|
long index_to_linear(index_t ind) const { return ind - first_index_window(); }
|
|
|
|
index_t linear_to_index(long lind) const { return lind + first_index_window(); }
|
2013-11-05 08:56:42 +01:00
|
|
|
|
2014-01-06 17:46:09 +01:00
|
|
|
/// Is the mesh only for positive omega_n (G(tau) real))
|
|
|
|
bool positive_only() const { return _positive_only;}
|
|
|
|
|
2013-12-30 22:31:36 +01:00
|
|
|
/**
|
|
|
|
* The mesh point
|
|
|
|
*
|
|
|
|
* * NB : the mesh point is also in this case a matsubara_freq.
|
|
|
|
**/
|
2013-11-20 15:11:29 +01:00
|
|
|
struct mesh_point_t : tag::mesh_point, matsubara_freq {
|
|
|
|
mesh_point_t() = default;
|
2013-11-05 08:56:42 +01:00
|
|
|
mesh_point_t(matsubara_freq_mesh const &mesh, index_t const &index_)
|
2014-09-03 14:03:31 +02:00
|
|
|
: matsubara_freq(index_, mesh.domain().beta, mesh.domain().statistic)
|
|
|
|
, first_index_window(mesh.first_index_window())
|
|
|
|
, last_index_window(mesh.last_index_window()) {}
|
|
|
|
mesh_point_t(matsubara_freq_mesh const &mesh) : mesh_point_t(mesh, mesh.first_index_window()) {}
|
2013-11-05 08:56:42 +01:00
|
|
|
void advance() { ++n; }
|
2014-09-03 14:03:31 +02:00
|
|
|
long linear_index() const { return n - first_index_window; }
|
2013-12-30 22:31:36 +01:00
|
|
|
long index() const { return n; }
|
2014-09-03 14:03:31 +02:00
|
|
|
bool at_end() const { return (n == last_index_window + 1); } // at_end means " one after the last one", as in STL
|
|
|
|
void reset() { n = first_index_window; }
|
2013-12-30 22:31:36 +01:00
|
|
|
|
|
|
|
private:
|
2014-09-03 14:03:31 +02:00
|
|
|
index_t first_index_window, last_index_window;
|
2013-11-05 08:56:42 +01:00
|
|
|
};
|
2014-09-03 14:03:31 +02:00
|
|
|
|
2013-12-30 22:31:36 +01:00
|
|
|
/// Accessing a point of the mesh from its index
|
|
|
|
mesh_point_t operator[](index_t i) const {
|
|
|
|
return {*this, i};
|
|
|
|
}
|
2013-11-05 08:56:42 +01:00
|
|
|
|
|
|
|
/// Iterating on all the points...
|
|
|
|
using const_iterator = mesh_pt_generator<matsubara_freq_mesh>;
|
|
|
|
const_iterator begin() const { return const_iterator(this); }
|
|
|
|
const_iterator end() const { return const_iterator(this, true); }
|
|
|
|
const_iterator cbegin() const { return const_iterator(this); }
|
|
|
|
const_iterator cend() const { return const_iterator(this, true); }
|
|
|
|
|
|
|
|
bool operator==(matsubara_freq_mesh const &M) const {
|
2014-01-07 14:30:40 +01:00
|
|
|
return (std::make_tuple(_dom, _n_pts, _positive_only) == std::make_tuple(M._dom, M._n_pts, M._positive_only));
|
2013-11-05 08:56:42 +01:00
|
|
|
}
|
|
|
|
bool operator!=(matsubara_freq_mesh const &M) const { return !(operator==(M)); }
|
|
|
|
|
|
|
|
/// Write into HDF5
|
|
|
|
friend void h5_write(h5::group fg, std::string subgroup_name, matsubara_freq_mesh const &m) {
|
|
|
|
h5::group gr = fg.create_group(subgroup_name);
|
|
|
|
h5_write(gr, "domain", m.domain());
|
|
|
|
h5_write(gr, "size", m.size());
|
2013-12-17 15:09:34 +01:00
|
|
|
if (m._positive_only) {
|
2013-12-30 22:31:36 +01:00
|
|
|
// kept ONLY for backward compatibility of archives
|
2013-12-17 15:09:34 +01:00
|
|
|
auto beta = m.domain().beta;
|
|
|
|
h5_write(gr, "min", Fermion ? M_PI / beta : 0);
|
|
|
|
h5_write(gr, "max", ((Fermion ? 1 : 0) + 2 * m.size()) * M_PI / beta);
|
|
|
|
h5_write(gr, "kind", 2);
|
|
|
|
} else { // A strange way : to preserve backward compatibility for old archive.
|
2014-05-04 15:30:32 +02:00
|
|
|
h5_write(gr, "start_at_0", (m._positive_only?1:0));
|
2013-12-17 15:09:34 +01:00
|
|
|
}
|
2013-11-05 08:56:42 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
/// Read from HDF5
|
|
|
|
friend void h5_read(h5::group fg, std::string subgroup_name, matsubara_freq_mesh &m) {
|
|
|
|
h5::group gr = fg.open_group(subgroup_name);
|
|
|
|
typename matsubara_freq_mesh::domain_t dom;
|
|
|
|
int L;
|
2014-05-04 15:30:32 +02:00
|
|
|
int s = 1;
|
2013-11-05 08:56:42 +01:00
|
|
|
h5_read(gr, "domain", dom);
|
|
|
|
h5_read(gr, "size", L);
|
2013-12-17 15:09:34 +01:00
|
|
|
if (gr.has_key("start_at_0")) h5_read(gr, "start_at_0", s);
|
2014-05-04 15:30:32 +02:00
|
|
|
m = matsubara_freq_mesh{std::move(dom), L, (s==1)};
|
2013-11-05 08:56:42 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
friend class boost::serialization::access;
|
2013-12-30 22:31:36 +01:00
|
|
|
/// BOOST Serialization
|
2013-11-05 08:56:42 +01:00
|
|
|
template <class Archive> void serialize(Archive &ar, const unsigned int version) {
|
2014-05-09 10:43:55 +02:00
|
|
|
ar &TRIQS_MAKE_NVP("beta", _dom.beta);
|
|
|
|
ar &TRIQS_MAKE_NVP("statistic", _dom.statistic);
|
|
|
|
//ar &TRIQS_MAKE_NVP("domain", _dom);
|
2014-05-02 16:00:12 +02:00
|
|
|
ar &TRIQS_MAKE_NVP("size", _n_pts);
|
|
|
|
ar &TRIQS_MAKE_NVP("kind", _positive_only);
|
2013-11-05 08:56:42 +01:00
|
|
|
}
|
|
|
|
|
2013-12-30 22:31:36 +01:00
|
|
|
/// Simple print (just blabla and the size)
|
2013-11-05 08:56:42 +01:00
|
|
|
friend std::ostream &operator<<(std::ostream &sout, matsubara_freq_mesh const &m) {
|
|
|
|
return sout << "Matsubara Freq Mesh of size " << m.size();
|
|
|
|
}
|
|
|
|
|
|
|
|
private:
|
|
|
|
domain_t _dom;
|
2014-01-07 14:30:40 +01:00
|
|
|
int _n_pts;
|
2013-11-05 08:56:42 +01:00
|
|
|
bool _positive_only;
|
2014-09-03 14:03:31 +02:00
|
|
|
long _first_index, _last_index, _first_index_window, _last_index_window;
|
2013-11-05 08:56:42 +01:00
|
|
|
};
|
2013-12-30 22:31:36 +01:00
|
|
|
|
|
|
|
//-------------------------------------------------------
|
|
|
|
|
|
|
|
/** \brief foreach for this mesh
|
|
|
|
*
|
|
|
|
* @param m : a mesh
|
|
|
|
* @param F : a function of synopsis auto F (matsubara_freq_mesh::mesh_point_t)
|
|
|
|
*
|
|
|
|
* Calls F on each point of the mesh, in arbitrary order.
|
|
|
|
**/
|
|
|
|
template <typename Lambda> void foreach(matsubara_freq_mesh const &m, Lambda F) {
|
|
|
|
for (auto const &w : m) F(w);
|
|
|
|
}
|
2013-11-20 15:11:29 +01:00
|
|
|
}
|
2013-11-05 08:56:42 +01:00
|
|
|
}
|
|
|
|
|