diff --git a/tests/test_fftw.cpp b/tests/test_fftw.cpp
index 854c2c0..7e586e6 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(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);
+ 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);
+ 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);
+ 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);
+ 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);
+ 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);
+ 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);
+ 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),
+ 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);
+ 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);
+ 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);
+ 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);
+ Grid grid{{size}, 2};
std::iota(grid.begin(), grid.end(), 0);
- GridHermitian grid_hermitian({size / 2 + 1}, 2);
- Grid result({size}, 2);
+ 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);
+ 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);
+ 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";
}
diff --git a/tests/test_grid.cpp b/tests/test_grid.cpp
index 41b7401..cbd20c3 100644
--- a/tests/test_grid.cpp
+++ b/tests/test_grid.cpp
@@ -1,305 +1,305 @@
/*
* 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 "grid.hh"
#include "grid_view.hh"
#include "model_type.hh"
#include "test.hh"
using namespace tamaas;
/* -------------------------------------------------------------------------- */
// Testing 1D creation
TEST(TestGridCreation, Creation1d) {
Grid grid{{5}, 2};
std::array correct_size{{5}};
ASSERT_TRUE(grid.sizes() == correct_size) << "Wrong sizes";
std::array correct_strides{{2, 1}};
ASSERT_TRUE(grid.getStrides() == correct_strides) << "Wrong strides";
}
// Testing 2D creation
TEST(TestGridCreation, Creation2d) {
- Grid grid({5, 2}, 3);
+ Grid grid{{5, 2}, 3};
std::array correct_size{{5, 2}};
ASSERT_TRUE(grid.sizes() == correct_size) << "Wrong sizes";
std::array correct_strides{{6, 3, 1}};
ASSERT_TRUE(grid.getStrides() == correct_strides) << "Wrong strides";
}
// Testing 3D creation
TEST(TestGridCreation, Creation3d) {
- Grid grid({8, 5, 2}, 3);
- std::array correct_size{{8, 5, 2}};
+ Grid grid{{8, 5, 2}, 3};
+ std::array correct_size{8, 5, 2};
ASSERT_TRUE(grid.sizes() == correct_size) << "Wrong sizes";
- std::array correct_strides{{30, 6, 3, 1}};
+ std::array correct_strides{30, 6, 3, 1};
ASSERT_TRUE(grid.getStrides() == correct_strides) << "Wrong strides";
}
/* -------------------------------------------------------------------------- */
TEST(TestWrap, Creation) {
std::array buffer;
std::array shape{5, 2};
span view{buffer.data(), 10};
// Fill values
std::iota(std::begin(buffer), std::end(buffer), 0);
// Wrap grid on view
Grid grid(shape.begin(), shape.end(), 1, view);
grid(1, 1) = 1;
ASSERT_TRUE(compare(view, buffer));
ASSERT_TRUE(compare(grid, buffer));
}
/* -------------------------------------------------------------------------- */
// Testing iterators in STL function iota
TEST(TestGridIterators, Iota) {
constexpr UInt N = 20;
- Grid grid({N}, 1);
+ Grid grid{{N}, 1};
std::iota(grid.begin(), grid.end(), 0);
- const UInt* p = grid.getInternalData();
+ const auto* p{grid.getInternalData()};
for (UInt i = 0; i < N; ++i)
ASSERT_TRUE(p[i] == i) << "Iota fill failed";
}
// Testing filling grid with OpenMP loop
TEST(TestGridIterators, OpenMPLoops) {
- Grid grid({20}, 1);
+ Grid grid{{20}, 1};
#ifndef TAMAAS_USE_CUDA
#pragma omp parallel for
#endif
for (auto it = grid.begin(); it < grid.end(); ++it) {
UInt i = it - grid.begin();
*it = i;
}
std::vector correct(20);
std::iota(correct.begin(), correct.end(), 0);
ASSERT_TRUE(compare(grid, correct)) << "Fill using OpenMP loop failed";
}
/* -------------------------------------------------------------------------- */
// Testing access operator
TEST(TestGridAccess, 3D) {
- Grid grid({1, 3, 5}, 3);
+ Grid grid{{1, 3, 5}, 3};
std::iota(grid.begin(), grid.end(), 0);
for (UInt i = 0; i < grid.sizes()[0]; ++i)
for (UInt j = 0; j < grid.sizes()[1]; ++j)
for (UInt k = 0; k < grid.sizes()[2]; ++k)
for (UInt m = 0; m < grid.getNbComponents(); ++m)
ASSERT_EQ(grid(i, j, k, m),
m + 3 * k + (3 * 5) * j + (3 * 5 * 3) * i);
- Grid grid1({5, 3}, 1);
+ Grid grid1{{5, 3}, 1};
grid1(2, 1, 0) = 1;
ASSERT_EQ(grid1(2 * 3 + 1), 1);
}
/* -------------------------------------------------------------------------- */
// Testing scalar simple loop-based operators
TEST(TestGridOperators, LoopOperators) {
- Grid grid({20}, 1);
+ Grid grid{{20}, 1};
grid = 1;
EXPECT_TRUE(std::all_of(grid.begin(), grid.end(), [](UInt x) {
return x == 1;
})) << "Assignement operator failed";
grid += 1;
EXPECT_TRUE(std::all_of(grid.begin(), grid.end(), [](UInt x) {
return x == 2;
})) << "Plus-equal operator failed";
}
// Testing loop-based functions with reductions
TEST(TestGridOperators, Stats) {
constexpr UInt n = 20;
const UInt N = mpi::allreduce(n);
- Grid grid({n}, 1);
+ Grid grid{{n}, 1};
std::iota(grid.begin(), grid.end(), 0);
std::vector v(n);
std::iota(v.begin(), v.end(), 0);
const auto b = v.cbegin(), e = v.cend();
Real min = mpi::allreduce(*std::min_element(b, e));
Real max = mpi::allreduce(*std::max_element(b, e));
Real sum = mpi::allreduce(std::accumulate(b, e, 0.));
Real mea = sum / N;
std::transform(b, e, v.begin(),
[mea](Real v) { return (v - mea) * (v - mea); });
Real acc = mpi::allreduce(std::accumulate(b, e, 0.));
Real var = acc / (N - 1);
EXPECT_DOUBLE_EQ(grid.min(), min) << "Minimum function failed";
EXPECT_DOUBLE_EQ(grid.max(), max) << "Maximum function failed";
EXPECT_DOUBLE_EQ(grid.sum(), sum) << "Sum function failed";
EXPECT_DOUBLE_EQ(grid.mean(), mea) << "Mean function failed";
EXPECT_DOUBLE_EQ(grid.var(), var) << "Var function failed";
}
/* -------------------------------------------------------------------------- */
TEST(TestGridView, View2D) {
- Grid grid3d({10, 10, 10}, 3);
+ Grid grid3d{{10, 10, 10}, 3};
std::iota(grid3d.begin(), grid3d.end(), 0);
for (UInt i : Loop::range(10)) {
auto grid_view = make_view(grid3d, i);
std::vector reference(300);
std::iota(reference.begin(), reference.end(), 300 * i);
EXPECT_TRUE(
std::equal(grid_view.begin(), grid_view.end(), reference.begin()))
<< "View on slice fail";
}
}
TEST(TestGridView, ViewOnComponent) {
- Grid grid3d({10, 9, 8}, 3), solution({10, 9, 8}, 3);
+ Grid grid3d{{10, 9, 8}, 3}, solution{{10, 9, 8}, 3};
grid3d = solution = 0;
auto view = make_component_view(grid3d, 2u);
std::iota(view.begin(), view.end(), 0);
for (UInt i = 0; i < solution.getNbPoints(); ++i)
solution(3 * i + 2) = i;
EXPECT_TRUE(std::equal(grid3d.begin(), grid3d.end(), solution.begin()))
<< "View on components fail";
view(9, 8, 7) = 1;
ASSERT_EQ(grid3d(9, 8, 7, 2), 1);
}
TEST(TestGridView, ViewCopy) {
- Grid grid3d({10, 10, 10}, 2);
- Grid copy, solution({10}, 1);
+ Grid grid3d{{10, 10, 10}, 2};
+ Grid copy, solution{{10}, 1};
auto view_on_slice = make_view(grid3d, 3, 4);
- Grid* view_on_slice_ptr = &view_on_slice;
+ auto* view_on_slice_ptr = &view_on_slice;
auto view = make_component_view(*view_on_slice_ptr, 1u);
std::iota(view.begin(), view.end(), 0);
std::iota(solution.begin(), solution.end(), 0);
copy = view;
EXPECT_TRUE(std::equal(copy.begin(), copy.end(), solution.begin()))
<< "Copy of view fail";
}
TEST(TestGridView, HigherOrderView) {
- Grid grid({10, 10}, 2);
+ Grid grid{{10, 10}, 2};
std::iota(grid.begin(), grid.end(), 0);
- GridView view(grid, {}, -1);
+ GridView view{grid, {}, -1};
EXPECT_TRUE(std::equal(grid.begin(), grid.end(), view.begin()))
<< "Higher order view fail";
}
/* -------------------------------------------------------------------------- */
struct BroadcastSet123 {
CUDA_LAMBDA inline void operator()(VectorProxy v) {
v(0) = 1;
v(1) = 2;
v(2) = 3;
}
};
TEST(TestGridOperators, BroadcastOperators) {
- Grid grid({10, 10}, 3), solution({10, 10}, 3);
+ Grid grid{{10, 10}, 3}, solution{{10, 10}, 3};
auto set = BroadcastSet123();
// Filling up solution
Loop::loop(set, range>(solution));
Vector v;
v(0) = 1;
v(1) = 2;
v(2) = 3;
grid = v;
EXPECT_TRUE(std::equal(grid.begin(), grid.end(), solution.begin()))
<< "Broadcast assignement failure";
v(1) = 1;
v(2) = 1;
solution += 1;
grid += v;
EXPECT_TRUE(std::equal(grid.begin(), grid.end(), solution.begin()))
<< "Broadcast += failure";
solution -= 1;
grid -= v;
EXPECT_TRUE(std::equal(grid.begin(), grid.end(), solution.begin()))
<< "Broadcast -= failure";
v(1) = 2;
v(2) = 3;
solution *= solution;
grid *= v;
EXPECT_TRUE(std::equal(grid.begin(), grid.end(), solution.begin()))
<< "Broadcast *= failure";
Loop::loop(set, range>(solution));
grid /= v;
EXPECT_TRUE(std::equal(grid.begin(), grid.end(), solution.begin()))
<< "Broadcast /= failure";
}
TEST(TestAllocation, HardType) {
std::array dims{4, 5};
auto grid = allocateGrid(dims, 1);
static_assert(
std::is_same>>::value,
"allocation type incorrect");
EXPECT_TRUE(std::equal(dims.begin(), dims.end(), grid->sizes().begin()));
EXPECT_EQ(grid->getNbComponents(), 1);
}
TEST(TestAllocation, SoftType) {
std::array dims{4, 5};
auto grid = allocateGrid(model_type::basic_2d, dims, 1);
static_assert(
std::is_same>>::value,
"allocation type incorrect");
EXPECT_EQ(grid->dataSize(), 20);
EXPECT_EQ(grid->getNbComponents(), 1);
}
diff --git a/tests/test_mpi.cpp b/tests/test_mpi.cpp
index e486972..fb5357b 100644
--- a/tests/test_mpi.cpp
+++ b/tests/test_mpi.cpp
@@ -1,205 +1,189 @@
/*
* 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/mpi/fftw_mpi_engine.hh"
#include "grid.hh"
#include "grid_hermitian.hh"
#include "grid_view.hh"
#include "partitioner.hh"
#include "test.hh"
#include
using namespace tamaas;
using fft = fftw::helper;
-/* -------------------------------------------------------------------------- */
-
-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; }
-};
-
/* -------------------------------------------------------------------------- */
TEST(TestMPIInterface, SequentialGuard) {
mpi::sequential_guard guard;
EXPECT_EQ(mpi::rank(), 0);
EXPECT_EQ(mpi::size(), 1);
ASSERT_EQ(mpi::comm::world()._comm, MPI_COMM_SELF);
}
/* -------------------------------------------------------------------------- */
TEST(TestFFTWInterface, MPISizes) {
const std::ptrdiff_t N0 = 100, N1 = 100;
std::ptrdiff_t local_n0, local_n0_start;
auto alloc_local = fftw_mpi_local_size_2d(N0, N1 / 2 + 1, mpi::comm::world(),
&local_n0, &local_n0_start);
const std::ptrdiff_t N[] = {N0, N1 / 2 + 1};
auto sizes = fftw::mpi::local_size_many(2, N, 1);
ASSERT_EQ(std::get<0>(sizes), alloc_local);
ASSERT_EQ(std::get<1>(sizes), local_n0);
ASSERT_EQ(std::get<2>(sizes), local_n0_start);
}
/* -------------------------------------------------------------------------- */
TEST(TestPartitioner, LocalSizes) {
const std::ptrdiff_t N0 = 100, N1 = 100;
std::ptrdiff_t local_n0, local_n0_start;
fftw_mpi_local_size_2d(N0, N1 / 2 + 1, mpi::comm::world(), &local_n0,
&local_n0_start);
auto local_size = Partitioner<2>::local_size({N0, N1 / 2 + 1});
ASSERT_EQ(local_size[0], local_n0);
ASSERT_EQ(local_size[1], N1 / 2 + 1);
ASSERT_EQ(Partitioner<2>::local_offset({N0, N1 / 2 + 1}), local_n0_start);
}
/* -------------------------------------------------------------------------- */
TEST(TestPartitioner, LocalOffsetInGrid) {
std::array N = {10, 10};
std::array Nglobal = {mpi::allreduce(N.front()), N.back()};
Grid local(N, 1), global(Nglobal, 1);
auto offset = Partitioner<2>::local_offset(local);
auto local_n0_start = Partitioner<2>::local_offset(Nglobal);
ASSERT_EQ(offset, &global(local_n0_start, 0) - &global(0, 0));
}
/* -------------------------------------------------------------------------- */
TEST(TestPartitioner, Scatter) {
- std::array N = {10, 10};
- Grid global(N, 3);
+ std::array N{10, 10};
+ Grid global{N, 3};
if (mpi::rank() != 0)
global.resize({0, 0});
std::iota(global.begin(), global.end(), 0);
auto local = Partitioner<2>::scatter(global);
auto gathered = Partitioner<2>::gather(local);
if (mpi::rank() != 0)
return;
ASSERT_TRUE(compare(gathered, global, AreFloatEqual()));
}
/* -------------------------------------------------------------------------- */
TEST(TestFFTWMPIEngine, BasicTransform) {
const std::ptrdiff_t N0 = 60, N1 = 60;
auto local_size = Partitioner<2>::local_size({N0, N1 / 2 + 1});
- Grid real({local_size[0], N1}, 1);
- GridHermitian spectral(local_size, 1);
+ Grid real{{local_size[0], N1}, 1};
+ GridHermitian spectral{local_size, 1};
auto offset = Partitioner<2>::local_offset(real);
std::iota(real.begin(), real.end(), offset);
FFTWMPIEngine().forward(real, spectral);
auto gathered = Partitioner<2>::gather(spectral);
if (mpi::rank() != 0)
return;
- Grid real_global({N0, N1}, 1);
- GridHermitian solution({N0, N1 / 2 + 1}, 1);
+ Grid real_global{{N0, N1}, 1};
+ GridHermitian solution{{N0, N1 / 2 + 1}, 1};
std::iota(real_global.begin(), real_global.end(), 0);
FFTWEngine().forward(real_global, solution);
// solution -= gathered;
// Logger().get(LogLevel::info) << solution << '\n';
// Increased error here because the iota input is bad:
// because operations are not the same in parallel,
// some parts of the output that should be close to zeros
// have different values in serial and parallel cases
ASSERT_TRUE(compare(gathered, solution, AreComplexEqual{1e-11}));
}
/* -------------------------------------------------------------------------- */
TEST(TestFFTWMPIEngine, BackwardsTransform) {
const std::ptrdiff_t N0 = 128, N1 = 128;
auto local_size = Partitioner<2>::local_size({N0, N1 / 2 + 1});
- Grid real({local_size[0], N1}, 1);
- GridHermitian spectral(local_size, 1);
+ Grid real{{local_size[0], N1}, 1};
+ GridHermitian spectral{local_size, 1};
real = 1.;
FFTWMPIEngine engine;
engine.forward(real, spectral);
real = 0;
engine.backward(real, spectral);
auto gathered = Partitioner<2>::gather(real);
if (mpi::rank() != 0)
return;
- Grid reference({N0, N1}, 1);
+ Grid reference{{N0, N1}, 1};
reference = 1.;
ASSERT_TRUE(compare(gathered, reference, AreFloatEqual()));
}
TEST(TestFFTWMPIEngine, ComponentsTransform) {
const std::ptrdiff_t N0 = 10, N1 = 10;
auto local_size = Partitioner<2>::local_size({N0, N1 / 2 + 1});
- Grid real({local_size[0], N1}, 2);
- GridHermitian spectral(local_size, 2);
+ Grid real{{local_size[0], N1}, 2};
+ GridHermitian spectral{local_size, 2};
real = 1;
FFTWMPIEngine().forward(real, spectral);
auto gathered = Partitioner<2>::gather(spectral);
if (mpi::rank() != 0)
return;
- Grid real_global({N0, N1}, 2);
- GridHermitian solution({N0, N1 / 2 + 1}, 2);
+ Grid real_global{{N0, N1}, 2};
+ GridHermitian solution{{N0, N1 / 2 + 1}, 2};
real_global = 1;
FFTWEngine().forward(real_global, solution);
ASSERT_TRUE(compare(gathered, solution, AreComplexEqual()));
}