diff --git a/tests/test_fftw.cpp b/tests/test_fftw.cpp index 301e9a6..854c2c0 100644 --- a/tests/test_fftw.cpp +++ b/tests/test_fftw.cpp @@ -1,240 +1,240 @@ /* * SPDX-License-Indentifier: AGPL-3.0-or-later * * Copyright (©) 2016-2023 EPFL (École Polytechnique Fédérale de Lausanne), * Laboratory (LSMS - Laboratoire de Simulation en Mécanique des Solides) * Copyright (©) 2020-2023 Lucas Frérot * * 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 . * */ /* -------------------------------------------------------------------------- */ #include "fftw/fftw_engine.hh" #include "grid.hh" #include "grid_hermitian.hh" #include "grid_view.hh" #include "test.hh" using namespace tamaas; using fft = fftw::helper; /* -------------------------------------------------------------------------- */ namespace fftw_impl { template struct span { T* ptr; std::size_t size; ~span() { fftw::free(ptr); } const T* begin() const { return ptr; } const T* end() const { return ptr + size; } T* begin() { return ptr; } T* end() { return ptr + size; } operator T*() { return ptr; } }; } // namespace fftw_impl /* -------------------------------------------------------------------------- */ -TEST(TestFFTEngine, FFT1D) { +TEST(TestFFTWEngine, FFT1D) { constexpr UInt size = 1000; FFTWEngine engine; fftw::span data{fft::alloc_real(size), size}; fftw::span solution{fft::alloc_complex(size / 2 + 1), size / 2 + 1}; fftw::plan solution_plan{ fftw::plan_1d_forward(size, data, solution, engine.flags())}; std::iota(data.begin(), data.end(), 0); fftw::execute(solution_plan); Grid grid({size}, 1); GridHermitian result({size / 2 + 1}, 1); std::iota(grid.begin(), grid.end(), 0); engine.forward(grid, result); ASSERT_TRUE(compare(result, solution, AreComplexEqual())) << "1D FFTW transform failed"; } /* -------------------------------------------------------------------------- */ TEST(TestFFTWEngine, FFT2D) { constexpr UInt size = 100; constexpr UInt rsize = size * size; constexpr UInt csize = size * (size / 2 + 1); FFTWEngine engine; fftw::span data{fft::alloc_real(rsize), rsize}; fftw::span solution{fft::alloc_complex(csize), csize}; fftw::plan solution_plan{ fftw::plan_2d_forward(size, size, data, solution, engine.flags())}; std::iota(data.begin(), data.end(), 0); fftw::execute(solution_plan); Grid grid({size, size}, 1); GridHermitian result({size, size / 2 + 1}, 1); std::iota(grid.begin(), grid.end(), 0); engine.forward(grid, result); ASSERT_TRUE(compare(result, solution, AreComplexEqual())) << "2D FFTW transform failed"; } /* -------------------------------------------------------------------------- */ TEST(TestFFTWEngine, FFT2DBackwards) { const std::ptrdiff_t N0 = 20, N1 = 20; Grid real({N0, N1}, 1); GridHermitian spectral({N0, N1 / 2 + 1}, 1); real = 1.; FFTWEngine engine; engine.forward(real, spectral); real = 0; engine.backward(real, spectral); Grid reference({N0, N1}, 1); reference = 1.; ASSERT_TRUE(compare(real, reference, AreFloatEqual())); } /* -------------------------------------------------------------------------- */ TEST(TestFFTWEngine, FFT1D2Comp) { constexpr UInt size = 20; /// 1D single component FFT should be working here Grid grid({size}, 2), data({size}, 1); std::iota(grid.begin(), grid.end(), 0); std::iota(data.begin(), data.end(), 0); GridHermitian result({size / 2 + 1}, 2), solution({size / 2 + 1}, 1); FFTWEngine engine; engine.forward(grid, result); std::iota(data.begin(), data.end(), 0); data *= 2; engine.forward(data, solution); const Real tol = 200 * std::numeric_limits::epsilon(); ASSERT_TRUE( compare(make_component_view(result, 0), solution, AreComplexEqual{tol})) << "1D FFTW transform with 2 components failed on 1st component"; data += 1; engine.forward(data, solution); ASSERT_TRUE( compare(make_component_view(result, 1), solution, AreComplexEqual{tol})) << "1D FFTW transform with 2 components failed on 2nd component"; } /* -------------------------------------------------------------------------- */ TEST(TestFFTWEngine, FFT2D3Comp) { constexpr UInt size = 20; /// 2D single component FFT should be working here Grid grid({size, size}, 3), data({size, size}, 1); std::iota(grid.begin(), grid.end(), 0); std::iota(data.begin(), data.end(), 0); data *= 3; GridHermitian result({size, size / 2 + 1}, 3), solution({size, size / 2 + 1}, 1); FFTWEngine engine; engine.forward(grid, result); constexpr Real tol = 5000 * std::numeric_limits::epsilon(); for (UInt i = 0; i < 3; ++i) { engine.forward(data, solution); ASSERT_TRUE( compare(make_component_view(result, i), solution, AreComplexEqual{tol})) << "2D FFTW transform with 3 components failed on " << i << "th component"; data += 1; } } /* -------------------------------------------------------------------------- */ TEST(TestFFTWEngine, FFT2DViewTransform) { constexpr UInt size = 20; Grid data({size, size}, 1); GridHermitian solution({size, size / 2 + 1}, 1); std::iota(std::begin(data), std::end(data), 0); FFTWEngine engine; engine.forward(data, solution); Grid grid({size, size}, 3); auto view = make_component_view(grid, 1); std::iota(view.begin(), view.end(), 0); GridHermitian result({size, size / 2 + 1}, 1); engine.forward(view, result); constexpr Real tol = 5000 * std::numeric_limits::epsilon(); ASSERT_TRUE(compare(result, solution, AreComplexEqual{tol})) << "Fourier transform on component view fail"; } /* -------------------------------------------------------------------------- */ TEST(TestFFTWEngine, FFTI1D2Comp) { constexpr UInt size = 20; Grid grid({size}, 2); std::iota(grid.begin(), grid.end(), 0); GridHermitian grid_hermitian({size / 2 + 1}, 2); Grid result({size}, 2); FFTWEngine engine; engine.forward(grid, grid_hermitian); engine.backward(result, grid_hermitian); ASSERT_TRUE(compare(grid, result, AreFloatEqual())) << "1D FFTI transform with 2 components failed"; } /* -------------------------------------------------------------------------- */ TEST(TestFFTWEngine, FFTI2D3Comp) { constexpr UInt size = 20; Grid grid({size, size}, 3); std::iota(grid.begin(), grid.end(), 0); GridHermitian grid_hermitian({size, size / 2 + 1}, 3); Grid result({size, size}, 3); FFTWEngine engine; engine.forward(grid, grid_hermitian); engine.backward(result, grid_hermitian); ASSERT_TRUE(compare(grid, result, AreFloatEqual())) << "2D FFTI transform with 3 components failed"; }