Page MenuHomec4science

fftw_engine.cpp
No OneTemporary

File Metadata

Created
Mon, Nov 11, 22:40

fftw_engine.cpp

/**
* @file
* @section LICENSE
*
* Copyright (©) 2016-2021 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 "fftw_engine.hh"
#include <algorithm>
#include <functional>
#include <numeric>
/* -------------------------------------------------------------------------- */
namespace tamaas {
FFTWEngine::plan_t& FFTWEngine::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
fftw::ptr<Real> in{nullptr};
fftw::ptr<complex_t> out{nullptr};
// Flags does not contain FFTW_ESTIMATE | FFTW_UNALIGNED => allocate in & out
if (not(_flags & FFTW_ESTIMATE and _flags & FFTW_UNALIGNED)) {
const auto prod = [](auto&& n) {
return std::accumulate(n.cbegin(), n.cend(), 1, std::multiplies<void>());
};
const auto hermit_n = GridHermitian<Real, 1>::hermitianDimensions(n);
in._ptr = fftw::helper<Real>::alloc_real(prod(n) * istride);
out._ptr = fftw::helper<Real>::alloc_complex(prod(hermit_n) * ostride);
}
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 detail

Event Timeline