30#include <fmt/format.h>
39namespace triqs::mesh {
104 mesh_point_t(
long n,
long d, uint64_t mhash,
double tau) : index_(n), data_index_(d), mesh_hash_(mhash), value_(tau) {}
107 [[nodiscard]]
long index()
const {
return index_; }
110 [[nodiscard]]
long data_index()
const {
return data_index_; }
113 [[nodiscard]]
double value()
const {
return value_; }
116 [[nodiscard]] uint64_t
mesh_hash() const noexcept {
return mesh_hash_; }
119 operator double()
const {
return value_; }
123 template <typename U> friend auto operator OP(mesh_point_t const &mp, U &&y) { return mp.value() OP std::forward<U>(y); } \
124 template <typename U> \
125 requires(not std::is_same_v<std::decay_t<U>, mesh_point_t>) \
126 friend auto operator OP(U &&x, mesh_point_t const &mp) { \
127 return std::forward<U>(x) OP mp.value(); \
137 long data_index_ = 0;
138 uint64_t mesh_hash_ = 0;
199 return points_scaled_[n];
219 [[nodiscard]] C2PY_PROPERTY_GET(
beta)
double beta() const noexcept {
return beta_; }
222 [[nodiscard]]
double inv_beta_x2() const noexcept {
return inv_beta_x2_; }
228 [[nodiscard]]
long size()
const {
return N_; }
234 [[nodiscard]] nda::vector_const_view<double>
points_standard()
const {
return points_standard_; }
237 [[nodiscard]] C2PY_PROPERTY_GET(
points) nda::vector_const_view<double>
points()
const {
return points_scaled_; }
240 [[nodiscard]] C2PY_PROPERTY_GET(
weights) nda::vector_const_view<double>
weights()
const {
return weights_; }
252 [[nodiscard]]
auto cend()
const {
return end(); }
262 auto stat_cstr = (m.stat_ == Boson ?
"Boson" :
"Fermion");
263 return sout << fmt::format(
"Chebyshev mesh with beta = {}, statistics = {}, N = {}", m.beta_, stat_cstr, m.N_);
270 void serialize(
auto &ar)
const { ar & beta_ & stat_ & N_ & mesh_hash_; }
277 ar & beta_ & stat_ & N_ & mesh_hash_;
278 if (N_ > 0) { init_arrays(); }
282 [[nodiscard]]
static std::string
hdf5_format() {
return "MeshChebyshev"; }
292 h5::group gr = g.create_group(name);
293 h5::write_hdf5_format(gr, m);
294 h5::write(gr,
"beta", m.beta_);
295 h5::write(gr,
"statistic", (m.stat_ == Fermion ?
"F" :
"B"));
296 h5::write(gr,
"n_chebyshev", m.N_);
307 h5::group gr = g.open_group(name);
308 h5::assert_hdf5_format(gr, m,
true);
310 auto beta = h5::read<double>(gr,
"beta");
311 auto statistic = (h5::read<std::string>(gr,
"statistic") ==
"F" ? Fermion : Boson);
312 auto N = h5::read<long>(gr,
"n_chebyshev");
320 inv_beta_x2_ = 2.0 / beta_;
323 points_scaled_ = nda::vector<double>(N_);
328 double inv_beta_x2_ = 2.0;
329 statistic_enum stat_ = Fermion;
331 uint64_t mesh_hash_ = 0;
334 nda::vector<double> points_standard_{};
335 nda::vector<double> points_scaled_{};
336 nda::vector<double> weights_{};
342 template <
typename F>
auto make_exact_result(F
const &f,
long i) {
343 using R = std::decay_t<
decltype(f(0))>;
344 if constexpr (nda::is_scalar_v<R>) {
346 }
else if constexpr (
requires { f(0).mesh(); }) {
347 return typename R::regular_type{f(i)};
349 return nda::make_regular(f(i));
354 template <
typename R,
typename F,
typename Po
ints,
typename Weights>
355 R barycentric_scalar(
double x, Points
const &points, Weights
const &weights, F
const &f,
long N) {
357 constexpr bool f_is_complex =
sizeof(f) > 2 *
sizeof(
void *);
359 if constexpr (f_is_complex) {
360 for (
long i = 0; i < N; ++i) {
361 if (x == points[i]) {
return f(i); }
364 constexpr long stack_threshold = 128;
365 R fval_stack[stack_threshold];
366 std::unique_ptr<R[]> fval_heap;
367 R *fval = (N <= stack_threshold) ? fval_stack : (fval_heap = std::make_unique<R[]>(N)).get();
368 for (
long i = 0; i < N; ++i) { fval[i] = f(i); }
372 for (
long i = 0; i < N; ++i) {
373 double q = weights[i] / (x - points[i]);
382 for (
long i = 0; i < N; ++i) {
383 double diff = x - points[i];
384 if (diff == 0.0) {
return f(i); }
385 double q = weights[i] / diff;
394 template <
typename F,
typename Po
ints,
typename Weights>
395 auto barycentric_array(
double x, Points
const &points, Weights
const &weights, F
const &f,
long N) {
396 using f_ret_t = std::decay_t<
decltype(f(0))>;
399 constexpr long stack_threshold = 512;
400 double q_stack[stack_threshold];
401 std::unique_ptr<double[]> q_heap;
402 double *q = (N <= stack_threshold) ? q_stack : (q_heap = std::make_unique<double[]>(N)).get();
404 double denominator = 0.0;
405 for (
long i = 0; i < N; ++i) {
406 double diff = x - points[i];
407 if (diff == 0.0) {
return make_exact_result(f, i); }
408 q[i] = weights[i] / diff;
411 double inv_denom = 1.0 / denominator;
412 for (
long i = 0; i < N; ++i) { q[i] *= inv_denom; }
415 if constexpr (
requires { f(0).mesh(); }) {
416 using gf_t =
typename f_ret_t::regular_type;
417 gf_t result{q[0] * f(0)};
418 for (
long i = 1; i < N; ++i) { result() += q[i] * f(i); }
421 constexpr bool f_returns_expression = !
requires { f(0).data(); };
423 auto result = nda::make_regular(q[0] * f(0));
424 using scalar_t =
typename decltype(result)::value_type;
425 scalar_t *r = result.data();
426 long const sz = result.size();
428 for (
long i = 1; i < N; ++i) {
429 auto const fi = [&] {
430 if constexpr (f_returns_expression)
431 return nda::make_regular(f(i));
435 scalar_t
const *fi_data = fi.data();
436 for (
long j = 0; j < sz; ++j) { r[j] += q[i] * fi_data[j]; }
459 inline auto evaluate(
chebyshev const &m,
auto const &f,
double tau) {
460 EXPECTS(m.
size() > 0 and tau >= 0 and tau <= m.
beta());
464 auto const &weights = m.
weights();
467 using f_ret_t = std::decay_t<
decltype(f(0))>;
469 if constexpr (nda::is_scalar_v<f_ret_t>)
470 return detail::barycentric_scalar<f_ret_t>(x, points, weights, f, N);
472 return detail::barycentric_array(x, points, weights, f, N);
iterator end()
Get an iterator past the last block.
iterator begin()
Get an iterator to the first block.
int size() const
Get the total number of blocks.
mesh_point_t()=default
Default constructor leaves the mesh point uninitialized.
chebyshev()=default
Default constructor constructs an empty mesh.
Mesh point of a triqs::mesh::chebyshev mesh.
double value() const
Get the value of the mesh point.
mesh_point_t()=default
Default constructor leaves the mesh point uninitialized.
uint64_t mesh_hash() const noexcept
Get the hash value of the parent mesh.
long index() const
Get the index of the mesh point.
chebyshev mesh_t
Parent mesh type.
long data_index() const
Get the data index of the mesh point.
mesh_point_t(long n, long d, uint64_t mhash, double tau)
Construct a mesh point with a given index , data index , hash value of the parent mesh and value .
Chebyshev imaginary time mesh type.
bool operator==(chebyshev const &) const =default
Equal-to comparison operator compares , and the particle statistics.
double inv_beta_x2() const noexcept
Get the precomputed for fast tau -> [-1, 1] mapping.
auto begin() const
Get an iterator to the beginning of the mesh.
value_t to_value(index_t n) const noexcept
Map an index to its corresponding value .
auto cbegin() const
Get a const iterator to the beginning of the mesh.
statistic_enum statistic() const noexcept
Get the particle statistics.
auto end() const
Get an iterator to the end of the mesh.
long size() const
Get the size of the mesh, i.e. the number of mesh points.
nda::vector_const_view< double > points_standard() const
Access to Chebyshev points on [-1, 1].
uint64_t mesh_hash() const
Get the hash value of the mesh.
long data_index_t
Data index type.
static std::string hdf5_format()
Get the HDF5 format tag.
mesh_point_t operator[](long d) const
Subscript operator to access a mesh point by its data index .
chebyshev(double beta, statistic_enum stat, long N)
Construct a Chebyshev mesh on with collocation points.
mesh_point_t operator()(long n) const
Function call operator to access a mesh point by its index .
nda::vector_const_view< double > weights() const
Access to barycentric weights.
friend void h5_read(h5::group g, std::string const &name, chebyshev &m)
Read a triqs::mesh::chebyshev mesh from HDF5.
auto cend() const
Get a const iterator to the end of the mesh.
index_t to_index(data_index_t d) const noexcept
Map a data index to the corresponding index .
data_index_t to_data_index(index_t n) const noexcept
Map an index to its corresponding data index .
double beta() const noexcept
Get the inverse temperature .
nda::vector_const_view< double > points() const
Access to Chebyshev points scaled to [0, beta].
void serialize(auto &ar) const
Serialize the mesh to a generic archive.
friend void h5_write(h5::group g, std::string const &name, chebyshev const &m)
Write a triqs::mesh::chebyshev mesh to HDF5.
double value_t
Value type (imaginary time tau).
bool is_index_valid(index_t n) const noexcept
Check if an index is valid.
friend std::ostream & operator<<(std::ostream &sout, chebyshev const &m)
Write a triqs::mesh::chebyshev mesh to a std::ostream.
chebyshev()=default
Default constructor constructs an empty mesh.
void deserialize(auto &ar)
Deserialize the mesh from a generic archive.
statistic_enum
Enum to specify particle statistics.
uint64_t hash(Ts &&...ts)
Generic hash function for multiple arguments.
nda::vector< double > chebyshev_barycentric_weights(long N)
Compute barycentric weights for Chebyshev points of the first kind.
nda::vector< double > chebyshev_points(long N)
Compute Chebyshev points of the first kind on the interval .
double from_standard_interval(double x, double a, double b)
Scale a value from the standard interval to interval .
Common macros used in TRIQS.
Provides various utilities used with Meshes.
Provides a generic random access iterator for 1D meshes.
A generic random access iterator for 1D meshes.
Provides utilities for Chebyshev polynomial computations.