Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Simplify fft + fix PeriodicSampling window #541

Merged
merged 15 commits into from
Jul 19, 2024
Merged
29 changes: 5 additions & 24 deletions include/ddc/kernels/fft.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -332,29 +332,7 @@ int N(ddc::DiscreteDomain<DDimX...> x_mesh)
static_assert(
(is_uniform_point_sampling_v<DDimX> && ...),
"DDimX dimensions should derive from UniformPointSampling");
return ddc::get<DDim>(x_mesh.extents());
}

template <typename DDim, typename... DDimX>
double a(ddc::DiscreteDomain<DDimX...> x_mesh)
{
static_assert(
(is_uniform_point_sampling_v<DDimX> && ...),
"DDimX dimensions should derive from UniformPointSampling");
return ((2 * N<DDim>(x_mesh) - 1) * coordinate(ddc::select<DDim>(x_mesh).front())
- coordinate(ddc::select<DDim>(x_mesh).back()))
/ 2 / (N<DDim>(x_mesh) - 1);
}

template <typename DDim, typename... DDimX>
double b(ddc::DiscreteDomain<DDimX...> x_mesh)
{
static_assert(
(is_uniform_point_sampling_v<DDimX> && ...),
"DDimX dimensions should derive from UniformPointSampling");
return ((2 * N<DDim>(x_mesh) - 1) * coordinate(ddc::select<DDim>(x_mesh).back())
- coordinate(ddc::select<DDim>(x_mesh).front()))
/ 2 / (N<DDim>(x_mesh) - 1);
return static_cast<int>(x_mesh.template extent<DDim>());
}

// core
Expand Down Expand Up @@ -595,7 +573,10 @@ typename DDimFx::template Impl<DDimFx, Kokkos::HostSpace> init_fourier_space(
ddc::Coordinate<typename DDimFx::continuous_dimension_type>(0),
ddc::Coordinate<typename DDimFx::continuous_dimension_type>(
2 * (ddc::detail::fft::N<DDimX>(x_mesh) - 1)
/ (ddc::detail::fft::b<DDimX>(x_mesh) - ddc::detail::fft::a<DDimX>(x_mesh))
* (ddc::detail::fft::N<DDimX>(x_mesh) - 1)
/ static_cast<double>(
ddc::detail::fft::N<DDimX>(x_mesh)
* (ddc::coordinate(x_mesh.back()) - ddc::coordinate(x_mesh.front())))
* Kokkos::numbers::pi),
ddc::DiscreteVector<DDimFx>(ddc::detail::fft::N<DDimX>(x_mesh)),
ddc::DiscreteVector<DDimFx>(ddc::detail::fft::N<DDimX>(x_mesh)));
Expand Down
11 changes: 9 additions & 2 deletions include/ddc/periodic_sampling.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -57,6 +57,8 @@ class PeriodicSampling : detail::PeriodicSamplingBase

std::size_t m_n_period {2};

bool m_odd_period {false};

public:
using discrete_dimension_type = PeriodicSampling;

Expand All @@ -75,6 +77,7 @@ class PeriodicSampling : detail::PeriodicSamplingBase
: m_origin(impl.m_origin)
, m_step(impl.m_step)
, m_n_period(impl.m_n_period)
, m_odd_period(impl.m_odd_period)
{
}

Expand All @@ -90,6 +93,7 @@ class PeriodicSampling : detail::PeriodicSamplingBase
: m_origin(origin)
, m_step(step)
, m_n_period(n_period)
, m_odd_period(static_cast<bool>(n_period % 2))
{
assert(step > 0);
assert(n_period > 0);
Expand Down Expand Up @@ -127,8 +131,11 @@ class PeriodicSampling : detail::PeriodicSamplingBase
{
return m_origin
+ continuous_element_type(
static_cast<int>((icoord.uid() + m_n_period / 2 - 1) % m_n_period)
- static_cast<int>(m_n_period / 2 - 1))
static_cast<int>(
(icoord.uid()
+ (m_n_period - static_cast<int>(m_odd_period)) / 2)
% m_n_period)
- static_cast<int>((m_n_period - static_cast<int>(m_odd_period)) / 2))
* m_step;
}
};
Expand Down
48 changes: 48 additions & 0 deletions tests/fft.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -199,6 +199,54 @@ struct RDimX;
struct RDimY;
struct RDimZ;

TEST(FourierMesh, Even)
{
double const a = -10;
double const b = 10;
std::size_t const Nx = 64;

DDom<DDim<RDimX>> const x_mesh(
ddc::init_discrete_space<DDim<RDimX>>(DDim<RDimX>::template init<DDim<RDimX>>(
ddc::Coordinate<RDimX>(a + (b - a) / Nx / 2),
ddc::Coordinate<RDimX>(b - (b - a) / Nx / 2),
DVect<DDim<RDimX>>(Nx))));
ddc::init_discrete_space<DFDim<ddc::Fourier<RDimX>>>(
ddc::init_fourier_space<DFDim<ddc::Fourier<RDimX>>>(
ddc::DiscreteDomain<DDim<RDimX>>(x_mesh)));

double const epsilon = 1e-14;
for (int i=-static_cast<int>(Nx)/2; i<=static_cast<int>(Nx-2)/2; i++) {
EXPECT_NEAR(
ddc::coordinate(ddc::DiscreteElement<DFDim<ddc::Fourier<RDimX>>>(i)),
2 * i * Kokkos::numbers::pi / (b - a),
epsilon);
}
}

TEST(FourierMesh, Odd)
{
double const a = -10;
double const b = 10;
std::size_t const Nx = 65;

DDom<DDim<RDimX>> const x_mesh(
ddc::init_discrete_space<DDim<RDimX>>(DDim<RDimX>::template init<DDim<RDimX>>(
ddc::Coordinate<RDimX>(a + (b - a) / Nx / 2),
ddc::Coordinate<RDimX>(b - (b - a) / Nx / 2),
DVect<DDim<RDimX>>(Nx))));
ddc::init_discrete_space<DFDim<ddc::Fourier<RDimX>>>(
ddc::init_fourier_space<DFDim<ddc::Fourier<RDimX>>>(
ddc::DiscreteDomain<DDim<RDimX>>(x_mesh)));

double const epsilon = 1e-14;
for (int i=-static_cast<int>(Nx-1)/2; i<=static_cast<int>(Nx-1)/2; i++) {
EXPECT_NEAR(
ddc::coordinate(ddc::DiscreteElement<DFDim<ddc::Fourier<RDimX>>>(i)),
2 * i * Kokkos::numbers::pi / (b - a),
epsilon);
}
}

#if fftw_serial_AVAIL
TEST(FFTNorm, OFF)
{
Expand Down
Loading