diff --git a/tests/test_fftw.cpp b/tests/test_fftw.cpp
index 854c2c0d..7e586e6c 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 <https://www.gnu.org/licenses/>.
  *
  */
 /* -------------------------------------------------------------------------- */
 #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<Real>;
 
 /* -------------------------------------------------------------------------- */
 
 namespace fftw_impl {
 template <typename T>
 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<Real> data{fft::alloc_real(size), size};
   fftw::span<fft::complex> solution{fft::alloc_complex(size / 2 + 1),
                                     size / 2 + 1};
 
   fftw::plan<Real> solution_plan{
       fftw::plan_1d_forward(size, data, solution, engine.flags())};
 
   std::iota(data.begin(), data.end(), 0);
   fftw::execute(solution_plan);
 
-  Grid<Real, 1> grid({size}, 1);
-  GridHermitian<Real, 1> result({size / 2 + 1}, 1);
+  Grid<Real, 1> grid{{size}, 1};
+  GridHermitian<Real, 1> 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<Real> data{fft::alloc_real(rsize), rsize};
   fftw::span<fft::complex> solution{fft::alloc_complex(csize), csize};
 
   fftw::plan<Real> solution_plan{
       fftw::plan_2d_forward(size, size, data, solution, engine.flags())};
 
   std::iota(data.begin(), data.end(), 0);
   fftw::execute(solution_plan);
 
-  Grid<Real, 2> grid({size, size}, 1);
-  GridHermitian<Real, 2> result({size, size / 2 + 1}, 1);
+  Grid<Real, 2> grid{{size, size}, 1};
+  GridHermitian<Real, 2> 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, 2> real({N0, N1}, 1);
-  GridHermitian<Real, 2> spectral({N0, N1 / 2 + 1}, 1);
+  Grid<Real, 2> real{{N0, N1}, 1};
+  GridHermitian<Real, 2> spectral{{N0, N1 / 2 + 1}, 1};
 
   real = 1.;
 
   FFTWEngine engine;
 
   engine.forward(real, spectral);
   real = 0;
   engine.backward(real, spectral);
 
-  Grid<Real, 2> reference({N0, N1}, 1);
+  Grid<Real, 2> 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<Real, 1> grid({size}, 2), data({size}, 1);
+  Grid<Real, 1> grid{{size}, 2}, data{{size}, 1};
   std::iota(grid.begin(), grid.end(), 0);
   std::iota(data.begin(), data.end(), 0);
-  GridHermitian<Real, 1> result({size / 2 + 1}, 2), solution({size / 2 + 1}, 1);
+  GridHermitian<Real, 1> 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<Real>::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<Real, 2> grid({size, size}, 3), data({size, size}, 1);
+  Grid<Real, 2> 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<Real, 2> result({size, size / 2 + 1}, 3),
+  GridHermitian<Real, 2> 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<Real>::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<Real, 2> data({size, size}, 1);
-  GridHermitian<Real, 2> solution({size, size / 2 + 1}, 1);
+  Grid<Real, 2> data{{size, size}, 1};
+  GridHermitian<Real, 2> solution{{size, size / 2 + 1}, 1};
   std::iota(std::begin(data), std::end(data), 0);
 
   FFTWEngine engine;
   engine.forward(data, solution);
 
-  Grid<Real, 2> grid({size, size}, 3);
+  Grid<Real, 2> grid{{size, size}, 3};
   auto view = make_component_view(grid, 1);
   std::iota(view.begin(), view.end(), 0);
 
-  GridHermitian<Real, 2> result({size, size / 2 + 1}, 1);
+  GridHermitian<Real, 2> result{{size, size / 2 + 1}, 1};
   engine.forward(view, result);
 
   constexpr Real tol = 5000 * std::numeric_limits<Real>::epsilon();
 
   ASSERT_TRUE(compare(result, solution, AreComplexEqual{tol}))
       << "Fourier transform on component view fail";
 }
 
 /* -------------------------------------------------------------------------- */
 TEST(TestFFTWEngine, FFTI1D2Comp) {
   constexpr UInt size = 20;
 
-  Grid<Real, 1> grid({size}, 2);
+  Grid<Real, 1> grid{{size}, 2};
   std::iota(grid.begin(), grid.end(), 0);
-  GridHermitian<Real, 1> grid_hermitian({size / 2 + 1}, 2);
-  Grid<Real, 1> result({size}, 2);
+  GridHermitian<Real, 1> grid_hermitian{{size / 2 + 1}, 2};
+  Grid<Real, 1> 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<Real, 2> grid({size, size}, 3);
+  Grid<Real, 2> grid{{size, size}, 3};
   std::iota(grid.begin(), grid.end(), 0);
-  GridHermitian<Real, 2> grid_hermitian({size, size / 2 + 1}, 3);
-  Grid<Real, 2> result({size, size}, 3);
+  GridHermitian<Real, 2> grid_hermitian{{size, size / 2 + 1}, 3};
+  Grid<Real, 2> 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 41b74017..cbd20c34 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 <https://www.gnu.org/licenses/>.
  *
  */
 /* -------------------------------------------------------------------------- */
 #include "grid.hh"
 #include "grid_view.hh"
 #include "model_type.hh"
 #include "test.hh"
 
 using namespace tamaas;
 
 /* -------------------------------------------------------------------------- */
 
 // Testing 1D creation
 TEST(TestGridCreation, Creation1d) {
   Grid<Real, 1> grid{{5}, 2};
   std::array<UInt, 1> correct_size{{5}};
   ASSERT_TRUE(grid.sizes() == correct_size) << "Wrong sizes";
 
   std::array<UInt, 2> correct_strides{{2, 1}};
   ASSERT_TRUE(grid.getStrides() == correct_strides) << "Wrong strides";
 }
 
 // Testing 2D creation
 TEST(TestGridCreation, Creation2d) {
-  Grid<Real, 2> grid({5, 2}, 3);
+  Grid<Real, 2> grid{{5, 2}, 3};
   std::array<UInt, 2> correct_size{{5, 2}};
   ASSERT_TRUE(grid.sizes() == correct_size) << "Wrong sizes";
 
   std::array<UInt, 3> correct_strides{{6, 3, 1}};
   ASSERT_TRUE(grid.getStrides() == correct_strides) << "Wrong strides";
 }
 
 // Testing 3D creation
 TEST(TestGridCreation, Creation3d) {
-  Grid<Real, 3> grid({8, 5, 2}, 3);
-  std::array<UInt, 3> correct_size{{8, 5, 2}};
+  Grid<Real, 3> grid{{8, 5, 2}, 3};
+  std::array<UInt, 3> correct_size{8, 5, 2};
   ASSERT_TRUE(grid.sizes() == correct_size) << "Wrong sizes";
 
-  std::array<UInt, 4> correct_strides{{30, 6, 3, 1}};
+  std::array<UInt, 4> correct_strides{30, 6, 3, 1};
   ASSERT_TRUE(grid.getStrides() == correct_strides) << "Wrong strides";
 }
 
 /* -------------------------------------------------------------------------- */
 TEST(TestWrap, Creation) {
   std::array<Real, 10> buffer;
   std::array<UInt, 2> shape{5, 2};
   span<Real> view{buffer.data(), 10};
 
   // Fill values
   std::iota(std::begin(buffer), std::end(buffer), 0);
 
   // Wrap grid on view
   Grid<Real, 2> 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<UInt, 1> grid({N}, 1);
+  Grid<UInt, 1> 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<UInt, 1> grid({20}, 1);
+  Grid<UInt, 1> 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<UInt> 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<UInt, 3> grid({1, 3, 5}, 3);
+  Grid<UInt, 3> 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<UInt, 2> grid1({5, 3}, 1);
+  Grid<UInt, 2> 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<UInt, 1> grid({20}, 1);
+  Grid<UInt, 1> 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<operation::plus>(n);
 
-  Grid<Real, 1> grid({n}, 1);
+  Grid<Real, 1> grid{{n}, 1};
   std::iota(grid.begin(), grid.end(), 0);
 
   std::vector<Real> v(n);
   std::iota(v.begin(), v.end(), 0);
 
   const auto b = v.cbegin(), e = v.cend();
   Real min = mpi::allreduce<operation::min>(*std::min_element(b, e));
   Real max = mpi::allreduce<operation::max>(*std::max_element(b, e));
   Real sum = mpi::allreduce<operation::plus>(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<operation::plus>(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<UInt, 3> grid3d({10, 10, 10}, 3);
+  Grid<UInt, 3> 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<UInt> 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<UInt, 3> grid3d({10, 9, 8}, 3), solution({10, 9, 8}, 3);
+  Grid<UInt, 3> 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<UInt, 3> grid3d({10, 10, 10}, 2);
-  Grid<UInt, 1> copy, solution({10}, 1);
+  Grid<UInt, 3> grid3d{{10, 10, 10}, 2};
+  Grid<UInt, 1> copy, solution{{10}, 1};
   auto view_on_slice = make_view(grid3d, 3, 4);
-  Grid<UInt, 1>* 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<UInt, 2> grid({10, 10}, 2);
+  Grid<UInt, 2> grid{{10, 10}, 2};
   std::iota(grid.begin(), grid.end(), 0);
-  GridView<Grid, UInt, 2, 3> view(grid, {}, -1);
+  GridView<Grid, UInt, 2, 3> 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<UInt, 3> v) {
     v(0) = 1;
     v(1) = 2;
     v(2) = 3;
   }
 };
 
 TEST(TestGridOperators, BroadcastOperators) {
-  Grid<UInt, 2> grid({10, 10}, 3), solution({10, 10}, 3);
+  Grid<UInt, 2> grid{{10, 10}, 3}, solution{{10, 10}, 3};
   auto set = BroadcastSet123();
 
   // Filling up solution
   Loop::loop(set, range<VectorProxy<UInt, 3>>(solution));
 
   Vector<UInt, 3> 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<VectorProxy<UInt, 3>>(solution));
   grid /= v;
 
   EXPECT_TRUE(std::equal(grid.begin(), grid.end(), solution.begin()))
       << "Broadcast /= failure";
 }
 
 TEST(TestAllocation, HardType) {
   std::array<UInt, 2> dims{4, 5};
   auto grid = allocateGrid<model_type::basic_2d, true, Real>(dims, 1);
   static_assert(
       std::is_same<decltype(grid), std::unique_ptr<Grid<Real, 2>>>::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<UInt, 2> dims{4, 5};
   auto grid = allocateGrid<true, Real>(model_type::basic_2d, dims, 1);
   static_assert(
       std::is_same<decltype(grid), std::unique_ptr<GridBase<Real>>>::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 e486972b..fb5357b2 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 <https://www.gnu.org/licenses/>.
  *
  */
 /* -------------------------------------------------------------------------- */
 #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 <fftw3-mpi.h>
 
 using namespace tamaas;
 using fft = fftw::helper<Real>;
 
-/* -------------------------------------------------------------------------- */
-
-template <typename T>
-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<UInt, 2> N = {10, 10};
   std::array<UInt, 2> Nglobal = {mpi::allreduce(N.front()), N.back()};
 
   Grid<UInt, 2> 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<UInt, 2> N = {10, 10};
-  Grid<Real, 2> global(N, 3);
+  std::array<UInt, 2> N{10, 10};
+  Grid<Real, 2> 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, 2> real({local_size[0], N1}, 1);
-  GridHermitian<Real, 2> spectral(local_size, 1);
+  Grid<Real, 2> real{{local_size[0], N1}, 1};
+  GridHermitian<Real, 2> 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, 2> real_global({N0, N1}, 1);
-  GridHermitian<Real, 2> solution({N0, N1 / 2 + 1}, 1);
+  Grid<Real, 2> real_global{{N0, N1}, 1};
+  GridHermitian<Real, 2> 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, 2> real({local_size[0], N1}, 1);
-  GridHermitian<Real, 2> spectral(local_size, 1);
+  Grid<Real, 2> real{{local_size[0], N1}, 1};
+  GridHermitian<Real, 2> 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<Real, 2> reference({N0, N1}, 1);
+  Grid<Real, 2> 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, 2> real({local_size[0], N1}, 2);
-  GridHermitian<Real, 2> spectral(local_size, 2);
+  Grid<Real, 2> real{{local_size[0], N1}, 2};
+  GridHermitian<Real, 2> spectral{local_size, 2};
 
   real = 1;
 
   FFTWMPIEngine().forward(real, spectral);
 
   auto gathered = Partitioner<2>::gather(spectral);
 
   if (mpi::rank() != 0)
     return;
 
-  Grid<Real, 2> real_global({N0, N1}, 2);
-  GridHermitian<Real, 2> solution({N0, N1 / 2 + 1}, 2);
+  Grid<Real, 2> real_global{{N0, N1}, 2};
+  GridHermitian<Real, 2> solution{{N0, N1 / 2 + 1}, 2};
 
   real_global = 1;
 
   FFTWEngine().forward(real_global, solution);
 
   ASSERT_TRUE(compare(gathered, solution, AreComplexEqual()));
 }