Page MenuHomec4science

fft_engine.cpp
No OneTemporary

File Metadata

Created
Tue, May 21, 18:45

fft_engine.cpp

/**
* @file
* @section LICENSE
*
* Copyright (©) 2016-2020 EPFL (École Polytechnique Fédérale de Lausanne),
* Laboratory (LSMS - Laboratoire de Simulation en Mécanique des Solides)
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as published
* by the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program 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 Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*
*/
/* -------------------------------------------------------------------------- */
#include "fft_engine.hh"
#include <algorithm>
#include <functional>
#include <numeric>
/* -------------------------------------------------------------------------- */
namespace tamaas {
namespace detail {
/// RAII helper for fftw_free
template <typename T>
struct fftw_ptr {
T* ptr;
~fftw_ptr() noexcept {
if (ptr)
fftw::free(ptr);
}
operator T*() { return ptr; }
};
} // namespace detail
FFTEngine::plan_t& FFTEngine::getPlans(key_t key) {
if (plans.find(key) != plans.end())
return plans[key];
const int rank = key.size() - 3; // dimension of fft
const auto components = key[rank];
std::vector<int> n(rank); // size of individual fft
std::copy_n(key.begin(), rank, n.begin());
const int howmany = components; // how many fft to compute
const int idist = 1,
odist = 1; // components are next to each other in memory
const int istride = key[rank + 1] * components,
ostride = key[rank + 2] * components;
int *inembed = nullptr, *onembed = nullptr; // row major
detail::fftw_ptr<Real> in{nullptr};
detail::fftw_ptr<fftw::helper<Real>::complex> out{nullptr};
// Flags does not contain FFTW_ESTIMATE | FFTW_UNALIGNED => allocate in & out
if (not(flags & FFTW_ESTIMATE and flags & FFTW_UNALIGNED)) {
const auto size =
std::accumulate(n.begin(), n.end(), 1, std::multiplies<void>()) *
components;
auto hermit_n = GridHermitian<Real, 1>::hermitianDimensions(n);
const auto hsize = std::accumulate(hermit_n.begin(), hermit_n.end(), 1,
std::multiplies<void>()) *
components;
in.ptr = fftw::helper<Real>::alloc_real(size);
out.ptr = fftw::helper<Real>::alloc_complex(hsize);
}
fftw::plan<Real> forward{
fftw::plan_many_forward(rank, n.data(), howmany, in, inembed, istride,
idist, out, onembed, ostride, odist, flags)};
fftw::plan<Real> backward{
fftw::plan_many_backward(rank, n.data(), howmany, out, onembed, ostride,
odist, in, inembed, istride, idist, flags)};
plans[key] = std::make_pair(std::move(forward), std::move(backward));
return plans[key];
}
} // namespace tamaas

Event Timeline