15#include <triqs/mesh/matsubara_freq.hpp>
16#include <triqs/utility/exceptions.hpp>
18namespace triqs::utility {
23 struct nfft_plan_deleter {
24 void operator()(nfft_plan *)
const;
28 inline std::vector<std::array<mesh::matsubara_freq, 1>> to_array_vector(std::vector<mesh::matsubara_freq>
const &v) {
29 std::vector<std::array<mesh::matsubara_freq, 1>> result;
30 result.reserve(v.size());
31 for (
auto const &mf : v) result.push_back({mf});
36 enum class nfft_type_t { type1, type3, direct };
38 template <
int Rank>
struct nfft_buf_t {
40 static_assert(Rank >= 1 and Rank <= 3,
"nfft_buf_t only supports Rank 1, 2, and 3");
43 nfft_buf_t() =
default;
58 nfft_buf_t(nda::array_view<dcomplex, Rank> fiw_arr_,
int buf_size_,
double beta_,
double tol_ = 1e-15);
78 nfft_buf_t(nda::array_view<dcomplex, 1> fiw_vec_, std::vector<std::array<mesh::matsubara_freq, Rank>> target_mf_,
int buf_size_, nfft_type_t type,
87 nfft_buf_t(nda::array_view<dcomplex, 1> fiw_vec_, std::vector<mesh::matsubara_freq>
const &target_mf_,
int buf_size_, nfft_type_t type,
90 : nfft_buf_t(std::move(fiw_vec_), detail::to_array_vector(target_mf_), buf_size_, type, tol_) {}
95 nfft_buf_t(nfft_buf_t
const &) =
delete;
96 nfft_buf_t &operator=(nfft_buf_t
const &) =
delete;
97 nfft_buf_t(nfft_buf_t &&) =
default;
98 nfft_buf_t &operator=(nfft_buf_t &&rhs)
noexcept;
101 void rebind(nda::array_view<dcomplex, Rank> new_fiw_arr) {
103 TRIQS_ASSERT((new_fiw_arr.shape() == fiw_arr.shape() or fiw_arr.empty())
104 and
" Nfft Buffer: Rebind to array of different shape not allowed ");
105 fiw_arr.rebind(new_fiw_arr);
109 void push_back(std::array<double, Rank>
const &tau_arr, dcomplex ftau) {
112 if (x_arr.empty()) NDA_RUNTIME_ERROR <<
" Using a default-constructed NFFT Buffer is not allowed\n";
114 if (nfft_type == nfft_type_t::type1) {
116 double tau_sum = 0.0;
117 for (
int r = 0; r < Rank; ++r) {
118 x_arr(r, buf_counter) = 2 * M_PI * (tau_arr[r] / beta - 0.5);
119 tau_sum += tau_arr[r];
121 fx_arr[buf_counter] = std::exp(dcomplex(0, M_PI * tau_sum / beta)) * ftau;
124 for (
int r = 0; r < Rank; ++r) x_arr(r, buf_counter) = tau_arr[r];
125 fx_arr[buf_counter] = ftau;
141 if (x_arr.empty()) NDA_RUNTIME_ERROR <<
" Using a default-constructed NFFT Buffer is not allowed\n";
144 if (is_empty())
return;
153 nfft_type_t nfft_type = nfft_type_t::type1;
156 nda::array_view<dcomplex, Rank> fiw_arr;
159 nda::array_view<dcomplex, 1> fiw_vec;
162 std::array<int64_t, Rank> niws{};
165 std::unique_ptr<detail::nfft_plan, detail::nfft_plan_deleter> plan;
177 int common_factor = 1;
180 int64_t n_targets = 0;
183 nda::array<double, 2> x_arr;
186 nda::vector<dcomplex> fx_arr;
189 nda::array<dcomplex, Rank> fk_arr;
192 nda::array<double, 2> s_arr;
195 nda::vector<dcomplex> fk_vec;
198 nda::array<long, 2> target_n;
201 int num_power2_levels = 0;
206 std::conditional_t<Rank == 1, nda::array<dcomplex, 2>, std::monostate> pow2_tbl;
210 std::conditional_t<Rank == 1, std::vector<std::vector<int>>, std::monostate> target_pow2_bits;
213 std::vector<int> primes;
214 std::array<nda::array<dcomplex, 2>, Rank> prime_pow_tbl;
215 std::array<std::vector<std::vector<int>>, Rank> target_prime_sums;
221 bool is_full()
const {
return buf_counter >= buf_size; }
224 bool is_empty()
const {
return buf_counter == 0; }
232 void set_pts(nda::array<double, 2> *tgt =
nullptr);
235 void do_nfft_type1();
238 void do_nfft_type3();
243 void do_direct_bitwise()
247 void do_direct_prime();