From 2a993021724e7ed8301e72c451c8b0b74d9550de Mon Sep 17 00:00:00 2001 From: Oliver Hahn Date: Sun, 30 Aug 2020 03:33:57 +0200 Subject: [PATCH] changed 'assign_function_of_grids...' type functions to variadic templates --- include/general.hh | 7 +++ include/grid_fft.hh | 129 +++++++++----------------------------------- 2 files changed, 31 insertions(+), 105 deletions(-) diff --git a/include/general.hh b/include/general.hh index d360e7d..05feb0a 100644 --- a/include/general.hh +++ b/include/general.hh @@ -30,8 +30,15 @@ #include "config_file.hh" +//! use to suppress warnings of unused variables #define _unused(x) ((void)(x)) +//! assert on all elements of a brace enclosed initializer list (useful for variadic templates) +inline void list_assert_all( const std::initializer_list& t ) +{ + for( auto b : t ) {assert(b);_unused(b);} +} + // include CMake controlled configuration settings #include "cmake_config.hh" diff --git a/include/grid_fft.hh b/include/grid_fft.hh index 7908da8..7489dd3 100644 --- a/include/grid_fft.hh +++ b/include/grid_fft.hh @@ -677,10 +677,12 @@ public: return real_t(locmin); } */ - template - void assign_function_of_grids_r(const functional &f, const grid_t &g) + + //! In real space, assigns the value of a functional of arbitrarily many grids, i.e. f(x) = f(g1(x),g2(x),...) + template + void assign_function_of_grids_r(const functional &f, Grids&... grids) { - assert(g.size(0) == size(0) && g.size(1) == size(1)); + list_assert_all( { ((grids.size(0)==this->size(0))&&(grids.size(1)==this->size(1))&&(grids.size(2)==this->size(2)))... } ); #pragma omp parallel for for (size_t i = 0; i < sizes_[0]; ++i) @@ -689,20 +691,17 @@ public: { for (size_t k = 0; k < sizes_[2]; ++k) { - auto &elem = this->relem(i, j, k); - const auto &elemg = g.relem(i, j, k); - - elem = f(elemg); + this->relem(i, j, k) = f((grids.relem(i, j, k))...); } } } } - template - void assign_function_of_grids_r(const functional &f, const grid1_t &g1, const grid2_t &g2) + //! In Fourier space, assigns the value of a functional of arbitrarily many grids, i.e. f(k) = f(g1(k),g2(k),...) + template + void assign_function_of_grids_k(const functional &f, Grids&... grids) { - assert(g1.size(0) == size(0) && g1.size(1) == size(1)); - assert(g2.size(0) == size(0) && g2.size(1) == size(1)); + list_assert_all( { ((grids.size(0)==this->size(0))&&(grids.size(1)==this->size(1))&&(grids.size(2)==this->size(2)))... } ); #pragma omp parallel for for (size_t i = 0; i < sizes_[0]; ++i) @@ -711,24 +710,18 @@ public: { for (size_t k = 0; k < sizes_[2]; ++k) { - //auto idx = this->get_idx(i,j,k); - auto &elem = this->relem(i, j, k); - - const auto &elemg1 = g1.relem(i, j, k); - const auto &elemg2 = g2.relem(i, j, k); - - elem = f(elemg1, elemg2); + this->kelem(i, j, k) = f((grids.kelem(i, j, k))...); } } } } - template - void assign_function_of_grids_r(const functional &f, const grid1_t &g1, const grid2_t &g2, const grid3_t &g3) + //! In Fourier space, assigns the value of a functional of arbitrarily many grids where first argument is the 3d array index + //! i.e. f[ijk] = f({ijk}, g1[ijk], g2[ijk], ...) + template + void assign_function_of_grids_ijk(const functional &f, Grids&... grids) { - assert(g1.size(0) == size(0) && g1.size(1) == size(1)); // && g1.size(2) == size(2)); - assert(g2.size(0) == size(0) && g2.size(1) == size(1)); // && g2.size(2) == size(2)); - assert(g3.size(0) == size(0) && g3.size(1) == size(1)); // && g3.size(2) == size(2)); + list_assert_all( { ((grids.size(0)==this->size(0))&&(grids.size(1)==this->size(1))&&(grids.size(2)==this->size(2)))... } ); #pragma omp parallel for for (size_t i = 0; i < sizes_[0]; ++i) @@ -737,23 +730,19 @@ public: { for (size_t k = 0; k < sizes_[2]; ++k) { - //auto idx = this->get_idx(i,j,k); - auto &elem = this->relem(i, j, k); - - const auto &elemg1 = g1.relem(i, j, k); - const auto &elemg2 = g2.relem(i, j, k); - const auto &elemg3 = g3.relem(i, j, k); - - elem = f(elemg1, elemg2, elemg3); + this->kelem(i, j, k) = f({i, j, k}, (grids.kelem(i, j, k))...); } } } } - template - void assign_function_of_grids_k(const functional &f, const grid_t &g) + //! In Fourier space, assigns the value of a functional of arbitrarily many grids where first argument is the k vector + //! i.e. f(k) = f(k, g1(k), g2(k), ...) + template + void assign_function_of_grids_kdep(const functional &f, Grids&... grids) { - assert(g.size(0) == size(0) && g.size(1) == size(1)); // && g.size(2) == size(2) ); + // check that all grids are same size + list_assert_all( { ((grids.size(0)==this->size(0))&&(grids.size(1)==this->size(1))&&(grids.size(2)==this->size(2)))... } ); #pragma omp parallel for for (size_t i = 0; i < sizes_[0]; ++i) @@ -762,77 +751,7 @@ public: { for (size_t k = 0; k < sizes_[2]; ++k) { - auto &elem = this->kelem(i, j, k); - const auto &elemg = g.kelem(i, j, k); - - elem = f(elemg); - } - } - } - } - - template - void assign_function_of_grids_k(const functional &f, const grid1_t &g1, const grid2_t &g2) - { - assert(g1.size(0) == size(0) && g1.size(1) == size(1)); // && g.size(2) == size(2) ); - assert(g2.size(0) == size(0) && g2.size(1) == size(1)); // && g.size(2) == size(2) ); - - #pragma omp parallel for - for (size_t i = 0; i < sizes_[0]; ++i) - { - for (size_t j = 0; j < sizes_[1]; ++j) - { - for (size_t k = 0; k < sizes_[2]; ++k) - { - auto &elem = this->kelem(i, j, k); - const auto &elemg1 = g1.kelem(i, j, k); - const auto &elemg2 = g2.kelem(i, j, k); - - elem = f(elemg1, elemg2); - } - } - } - } - - template - void assign_function_of_grids_kdep(const functional &f, const grid_t &g) - { - assert(g.size(0) == size(0) && g.size(1) == size(1)); // && g.size(2) == size(2) ); - - #pragma omp parallel for - for (size_t i = 0; i < sizes_[0]; ++i) - { - for (size_t j = 0; j < sizes_[1]; ++j) - { - for (size_t k = 0; k < sizes_[2]; ++k) - { - auto &elem = this->kelem(i, j, k); - const auto &elemg = g.kelem(i, j, k); - - elem = f(this->get_k(i, j, k), elemg); - } - } - } - } - - template - void assign_function_of_grids_kdep(const functional &f, const grid1_t &g1, const grid2_t &g2) - { - assert(g1.size(0) == size(0) && g1.size(1) == size(1) && g1.size(2) == size(2) ); - assert(g2.size(0) == size(0) && g2.size(1) == size(1) && g2.size(2) == size(2) ); - - #pragma omp parallel for - for (size_t i = 0; i < size(0); ++i) - { - for (size_t j = 0; j < size(1); ++j) - { - for (size_t k = 0; k < size(2); ++k) - { - auto &elem = this->kelem(i, j, k); - const auto &elemg1 = g1.kelem(i, j, k); - const auto &elemg2 = g2.kelem(i, j, k); - - elem = f(this->get_k(i, j, k), elemg1, elemg2); + this->kelem(i, j, k) = f(this->get_k(i, j, k), (grids.kelem(i, j, k))...); } } }