diff --git a/test/test_model/test_solid_mechanics_model/CMakeLists.txt b/test/test_model/test_solid_mechanics_model/CMakeLists.txt
index da7f1059a..90943a0a3 100644
--- a/test/test_model/test_solid_mechanics_model/CMakeLists.txt
+++ b/test/test_model/test_solid_mechanics_model/CMakeLists.txt
@@ -1,107 +1,108 @@
 #===============================================================================
 # @file   CMakeLists.txt
 #
 # @author Guillaume Anciaux <guillaume.anciaux@epfl.ch>
 #
 # @date creation: Fri Sep 03 2010
 # @date last modification: Tue Jan 19 2016
 #
 # @brief  configuratio for SolidMechanicsModel tests
 #
 # @section LICENSE
 #
 # Copyright (©)  2010-2012, 2014,  2015 EPFL  (Ecole Polytechnique  Fédérale de
 # Lausanne)  Laboratory (LSMS  -  Laboratoire de  Simulation  en Mécanique  des
 # Solides)
 #
 # Akantu is free  software: you can redistribute it and/or  modify it under the
 # terms  of the  GNU Lesser  General Public  License as  published by  the Free
 # Software Foundation, either version 3 of the License, or (at your option) any
 # later version.
 #
 # Akantu 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  Lesser General  Public License  for more
 # details.
 #
 # You should  have received  a copy  of the GNU  Lesser General  Public License
 # along with Akantu. If not, see <http://www.gnu.org/licenses/>.
 #
 # @section DESCRIPTION
 #
 #===============================================================================
 
 add_akantu_test(test_materials "test_materials")
 add_akantu_test(patch_tests "patch_tests")
 add_akantu_test(test_cohesive "cohesive_test")
 add_akantu_test(test_embedded_interface "test_embedded_interface")
 add_akantu_test(test_energies "test energies")
 #===============================================================================
 
 #===============================================================================
 add_mesh(test_cube3d_two_mat_mesh cube_two_materials.geo 3 1)
 register_test(test_solid_mechanics_model_reassign_material
   SOURCES test_solid_mechanics_model_reassign_material.cc
   DEPENDS test_cube3d_two_mat_mesh
   FILES_TO_COPY two_materials.dat
   PACKAGE parallel implicit
   PARALLEL
   )
 
 #===============================================================================
 register_test(test_solid_mechanics_model_material_eigenstrain
   SOURCES test_solid_mechanics_model_material_eigenstrain.cc
   FILES_TO_COPY cube_3d_tet_4.msh; material_elastic_plane_strain.dat
   PACKAGE implicit
   )
 
 #===============================================================================
 register_test(test_material_selector
   SOURCES test_material_selector.cc
   FILES_TO_COPY material_selector.dat material_selector.msh
   PACKAGE core
   )
 
 add_mesh(bar_segment_2 patch_tests/data/bar_segment.geo
   DIM 1 ORDER 1 OUTPUT bar_segment_2.msh)
 add_mesh(bar_segment_3 patch_tests/data/bar_segment.geo
   DIM 1 ORDER 2 OUTPUT bar_segment_3.msh)
 add_mesh(bar_triangle_3 patch_tests/data/bar_triangle.geo
   DIM 2 ORDER 1 OUTPUT bar_triangle_3.msh)
 add_mesh(bar_triangle_6 patch_tests/data/bar_triangle.geo
   DIM 2 ORDER 2 OUTPUT bar_triangle_6.msh)
 add_mesh(bar_quadrangle_4 patch_tests/data/bar_quadrangle.geo
   DIM 2 ORDER 1 OUTPUT bar_quadrangle_4.msh)
 add_mesh(bar_quadrangle_8 patch_tests/data/bar_quadrangle.geo
   DIM 2 ORDER 2 OUTPUT bar_quadrangle_8.msh)
 add_mesh(bar_tetrahedron_4 patch_tests/data/bar_tetrahedron.geo
   DIM 3 ORDER 1 OUTPUT  bar_tetrahedron_4.msh)
 add_mesh(bar_tetrahedron_10 patch_tests/data/bar_tetrahedron.geo
   DIM 3 ORDER 2 OUTPUT bar_tetrahedron_10.msh)
 add_mesh(bar_hexahedron_8  patch_tests/data/bar_hexahedron.geo
   DIM 3 ORDER 1 OUTPUT bar_hexahedron_8.msh)
 add_mesh(bar_hexahedron_20 patch_tests/data/bar_hexahedron.geo
   DIM 3 ORDER 2 OUTPUT bar_hexahedron_20.msh)
 add_mesh(bar_pentahedron_6 patch_tests/data/bar_pentahedron.geo
   DIM 3 ORDER 1 OUTPUT bar_pentahedron_6.msh)
 add_mesh(bar_pentahedron_15 patch_tests/data/bar_pentahedron.geo
   DIM 3 ORDER 2 OUTPUT bar_pentahedron_15.msh)
 
 
 #===============================================================================
 # dynamics tests
 #===============================================================================
 register_gtest_sources(
   SOURCES test_solid_mechanics_model_dynamics.cc
   FILES_TO_COPY test_solid_mechanics_model_dynamics_material.dat
   PACKAGE core
+  PARALLEL
   )
 
 register_gtest_test(test_solid_mechanics_model
   DEPENDS bar_segment_2 bar_segment_3
           bar_triangle_3 bar_triangle_6
 	  bar_quadrangle_4 bar_quadrangle_8
 	  bar_tetrahedron_4 bar_tetrahedron_10
 	  bar_hexahedron_8 bar_hexahedron_20
 	  bar_pentahedron_6 bar_pentahedron_15
   )
diff --git a/test/test_model/test_solid_mechanics_model/test_energies/test_solid_mechanics_model_work_dynamics.cc b/test/test_model/test_solid_mechanics_model/test_energies/test_solid_mechanics_model_work_dynamics.cc
index 72690cadb..11fa0cfd8 100644
--- a/test/test_model/test_solid_mechanics_model/test_energies/test_solid_mechanics_model_work_dynamics.cc
+++ b/test/test_model/test_solid_mechanics_model/test_energies/test_solid_mechanics_model_work_dynamics.cc
@@ -1,158 +1,158 @@
 /**
  * @file   test_solid_mechanics_model_work_dynamics.cc
  *
  * @author Tobias Brink <tobias.brink@epfl.ch>
  *
  * @date creation: Tue Dec 15 2017
  * @date last modification: Dec Nov 15 2017
  *
  * @brief  test work in dynamic simulations
  *
  * @section description
  *
  * Assuming that the kinetic energy and the potential energy of the
  * linear elastic material are bug free, the work in a dynamic
  * simulation must equal the change in internal energy (first law of
  * thermodynamics). Work in dynamics is an infinitesimal work Fds,
  * thus we need to integrate it and compare at the end. In this test,
  * we use one Dirichlet boundary condition (with u = 0.0, 0.01, and
  * -0.01) and one Neumann boundary condition for F on the opposite
  * side. Then we do a few steps to get reference energies for work and
  * internal energy. After more steps, the change in both work and
  * internal energy must be equal.
  *
  * @section LICENSE
  *
  * Copyright (©)  2017 EPFL  (Ecole Polytechnique  Fédérale de
  * Lausanne)  Laboratory (LSMS  -  Laboratoire de  Simulation  en Mécanique  des
  * Solides)
  *
  * Akantu is free  software: you can redistribute it and/or  modify it under the
  * terms  of the  GNU Lesser  General Public  License as  published by  the Free
  * Software Foundation, either version 3 of the License, or (at your option) any
  * later version.
  *
  * Akantu 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  Lesser General  Public License  for more
  * details.
  *
  * You should  have received  a copy  of the GNU  Lesser General  Public License
  * along with Akantu. If not, see <http://www.gnu.org/licenses/>.
  *
  */
 
 /* -------------------------------------------------------------------------- */
 #include "../test_solid_mechanics_model_fixture.hh"
 /* -------------------------------------------------------------------------- */
 
 using namespace akantu;
 
 namespace {
 
 template <typename type_>
 class TestSMMFixtureWorkDynamic : public TestSMMFixture<type_> {
 public:
   void SetUp() override {
     this->mesh_file = "../bar" + aka::to_string(this->type) + ".msh";
     TestSMMFixture<type_>::SetUp();
 
     getStaticParser().parse("test_solid_mechanics_model_"
                             "work_material.dat");
 
     /// model initialization
     this->model->initFull();
 
     /// Create a node group for Neumann BCs.
     auto & apply_force_grp = this->mesh->createNodeGroup("apply_force");
     auto & fixed_grp = this->mesh->createNodeGroup("fixed");
 
     const auto & pos = this->mesh->getNodes();
     const auto & lower = this->mesh->getLowerBounds();
     const auto & upper = this->mesh->getUpperBounds();
 
     UInt i = 0;
     for (auto && posv : make_view(pos, this->spatial_dimension)) {
       if (posv(_x) > upper(_x) - 1e-6) {
         apply_force_grp.add(i);
       } else if (posv(_x) < lower(_x) + 1e-6) {
         fixed_grp.add(i);
       }
       ++i;
     }
 
     this->mesh->createElementGroupFromNodeGroup("el_apply_force", "apply_force",
                                                 this->spatial_dimension - 1);
     this->mesh->createElementGroupFromNodeGroup("el_fixed", "fixed",
                                                 this->spatial_dimension - 1);
 
     Vector<Real> surface_traction(this->spatial_dimension);
     surface_traction(_x) = 0.5;
     if (this->spatial_dimension == 1) {
       // TODO: this is a hack to work
       //      around non-implemented
       //      BC::Neumann::FromTraction for 1D
       auto & force = this->model->getForce();
 
       for (auto && pair : zip(make_view(pos, this->spatial_dimension),
                               make_view(force, this->spatial_dimension))) {
         auto & posv = std::get<0>(pair);
         auto & forcev = std::get<1>(pair);
         if (posv(_x) > upper(_x) - 1e-6) {
           forcev(_x) = surface_traction(_x);
         }
       }
     } else {
       this->model->applyBC(BC::Neumann::FromTraction(surface_traction),
                            "el_apply_force");
     }
 
     /// set up timestep
     auto time_step = this->model->getStableTimeStep() * 0.1;
     this->model->setTimeStep(time_step);
   }
 };
 
-TYPED_TEST_CASE(TestSMMFixtureWorkDynamic, types);
+TYPED_TEST_CASE(TestSMMFixtureWorkDynamic, gtest_element_types);
 
 /* TODO: this is currently disabled for terrible results and performance
 TYPED_TEST(TestSMMFixtureBar, WorkImplicit) {
   test_body(*(this->model), *(this->mesh), _implicit_dynamic, 500);
 }
 */
 // model.assembleMassLumped();
 TYPED_TEST(TestSMMFixtureWorkDynamic, WorkExplicit) {
   /// Do the sim
   std::vector<Real> displacements{0.00, 0.01, -0.01};
 
   for (auto && u : displacements) {
     this->model->applyBC(BC::Dirichlet::FixedValue(u, _x), "el_fixed");
 
     // First, "equilibrate" a bit to get a reference state of total
     // energy and work. This is needed when we have a Dirichlet with
     // finite displacement on one side.
     for (UInt i = 0; i < 25; ++i) {
       this->model->solveStep();
     }
     // Again, work reported by Akantu is infinitesimal (dW) and we
     // need to integrate a while to get a decent value.
     double Etot0 =
         this->model->getEnergy("potential") + this->model->getEnergy("kinetic");
     double W = 0.0;
     for (UInt i = 0; i < 200; ++i) {
       /// Solve.
       this->model->solveStep();
 
       const auto dW = this->model->getEnergy("external work");
 
       W += dW;
     }
     // Finally check.
     const auto Epot = this->model->getEnergy("potential");
     const auto Ekin = this->model->getEnergy("kinetic");
 
     EXPECT_NEAR(W, Ekin + Epot - Etot0, 5e-2);
     // Sadly not very exact for such a coarse mesh.
   }
 }
 }
diff --git a/test/test_model/test_solid_mechanics_model/test_solid_mechanics_model_dynamics.cc b/test/test_model/test_solid_mechanics_model/test_solid_mechanics_model_dynamics.cc
index 4d8b3a158..c049452ed 100644
--- a/test/test_model/test_solid_mechanics_model/test_solid_mechanics_model_dynamics.cc
+++ b/test/test_model/test_solid_mechanics_model/test_solid_mechanics_model_dynamics.cc
@@ -1,281 +1,314 @@
 /**
  * @file   test_solid_mechanics_model_cube3d.cc
  *
  * @author Guillaume Anciaux <guillaume.anciaux@epfl.ch>
  *
  * @date creation: Wed Aug 04 2010
  * @date last modification: Thu Aug 06 2015
  *
  * @brief  test of the class SolidMechanicsModel on the 3d cube
  *
  * @section LICENSE
  *
  * Copyright (©)  2010-2012, 2014,  2015 EPFL  (Ecole Polytechnique  Fédérale de
  * Lausanne)  Laboratory (LSMS  -  Laboratoire de  Simulation  en Mécanique  des
  * Solides)
  *
  * Akantu is free  software: you can redistribute it and/or  modify it under the
  * terms  of the  GNU Lesser  General Public  License as  published by  the Free
  * Software Foundation, either version 3 of the License, or (at your option) any
  * later version.
  *
  * Akantu 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  Lesser General  Public License  for more
  * details.
  *
  * You should  have received  a copy  of the GNU  Lesser General  Public License
  * along with Akantu. If not, see <http://www.gnu.org/licenses/>.
  *
  */
 
 /* -------------------------------------------------------------------------- */
 #include "boundary_condition_functor.hh"
 #include "test_solid_mechanics_model_fixture.hh"
 /* -------------------------------------------------------------------------- */
 
 using namespace akantu;
 
 namespace {
 
 constexpr Real A = 1e-1;
 constexpr Real E = 1.;
 constexpr Real poisson = .3;
 constexpr Real lambda = E * poisson / (1. + poisson) / (1. - 2. * poisson);
 constexpr Real mu = E / 2 / (1. + poisson);
 constexpr Real rho = 1.;
 const Real cp = std::sqrt((lambda + 2 * mu) / rho);
 const Real cs = std::sqrt(mu / rho);
 const Real c = std::sqrt(E / rho);
 
 const Vector<Real> k = {.5, 0., 0.};
 const Vector<Real> psi1 = {0., 0., 1.};
 const Vector<Real> psi2 = {0., 1., 0.};
 const Real knorm = k.norm();
 
-using verif_func = std::function<void(
-    Vector<Real> & disp, const Vector<Real> & coord, Real current_time)>;
-
-template <UInt spatial_dimension> verif_func solution_disp;
-template <UInt spatial_dimension> verif_func solution_vel;
-
-template <>
-verif_func solution_disp<1> =
-    [](Vector<Real> & disp, const Vector<Real> & coord, Real current_time) {
-      const auto & x = coord(_x);
-      const Real omega = c * k[0];
-      disp(_x) = A * cos(k[0] * x - omega * current_time);
-    };
-
-template <>
-verif_func solution_vel<1> =
-    [](Vector<Real> & vel, const Vector<Real> & coord, Real current_time) {
-      const auto & x = coord(_x);
-      const Real omega = c * k[0];
-      vel(_x) = omega * A * sin(k[0] * x - omega * current_time);
-    };
-
-template <>
-verif_func solution_disp<2> =
-    [](Vector<Real> & disp, const Vector<Real> & X, Real current_time) {
-      Vector<Real> kshear = {k[1], k[0]};
-      Vector<Real> kpush = {k[0], k[1]};
-
-      const Real omega_p = knorm * cp;
-      const Real omega_s = knorm * cs;
-
-      Real phase_p = X.dot(kpush) - omega_p * current_time;
-      Real phase_s = X.dot(kpush) - omega_s * current_time;
-
-      disp = A * (kpush * cos(phase_p) + kshear * cos(phase_s));
-    };
-
-template <>
-verif_func solution_vel<2> = [](Vector<Real> & vel, const Vector<Real> & X,
-                                Real current_time) {
-  Vector<Real> kshear = {k[1], k[0]};
-  Vector<Real> kpush = {k[0], k[1]};
-
-  const Real omega_p = knorm * cp;
-  const Real omega_s = knorm * cs;
-
-  Real phase_p = X.dot(kpush) - omega_p * current_time;
-  Real phase_s = X.dot(kpush) - omega_s * current_time;
-
-  vel = A * (kpush * omega_p * cos(phase_p) + kshear * omega_s * cos(phase_s));
+/* -------------------------------------------------------------------------- */
+template <UInt dim> struct Verification {};
+
+/* -------------------------------------------------------------------------- */
+template <> struct Verification<1> {
+  void displacement(Vector<Real> & disp, const Vector<Real> & coord,
+                    Real current_time) {
+    const auto & x = coord(_x);
+    const Real omega = c * k[0];
+    disp(_x) = A * cos(k[0] * x - omega * current_time);
+  }
+
+  void velocity(Vector<Real> & vel, const Vector<Real> & coord,
+                Real current_time) {
+    const auto & x = coord(_x);
+    const Real omega = c * k[0];
+    vel(_x) = omega * A * sin(k[0] * x - omega * current_time);
+  }
 };
 
-template <>
-verif_func solution_disp<3> =
-    [](Vector<Real> & disp, const Vector<Real> & coord, Real current_time) {
-      const auto & X = coord;
-      Vector<Real> kpush = k;
-      Vector<Real> kshear1(3);
-      Vector<Real> kshear2(3);
-      kshear1.crossProduct(k, psi1);
-      kshear2.crossProduct(k, psi2);
+/* -------------------------------------------------------------------------- */
+template <> struct Verification<2> {
+  void displacement(Vector<Real> & disp, const Vector<Real> & X,
+                    Real current_time) {
+    Vector<Real> kshear = {k[1], k[0]};
+    Vector<Real> kpush = {k[0], k[1]};
 
-      const Real omega_p = knorm * cp;
-      const Real omega_s = knorm * cs;
+    const Real omega_p = knorm * cp;
+    const Real omega_s = knorm * cs;
 
-      Real phase_p = X.dot(kpush) - omega_p * current_time;
-      Real phase_s = X.dot(kpush) - omega_s * current_time;
+    Real phase_p = X.dot(kpush) - omega_p * current_time;
+    Real phase_s = X.dot(kpush) - omega_s * current_time;
 
-      disp = A * (kpush * cos(phase_p) + kshear1 * cos(phase_s) +
-                  kshear2 * cos(phase_s));
+    disp = A * (kpush * cos(phase_p) + kshear * cos(phase_s));
+  }
+
+  void velocity(Vector<Real> & vel, const Vector<Real> & X, Real current_time) {
+    Vector<Real> kshear = {k[1], k[0]};
+    Vector<Real> kpush = {k[0], k[1]};
 
-    };
+    const Real omega_p = knorm * cp;
+    const Real omega_s = knorm * cs;
 
-template <>
-verif_func solution_vel<3> = [](Vector<Real> & vel, const Vector<Real> & coord,
-                                Real current_time) {
-  const auto & X = coord;
-  Vector<Real> kpush = k;
-  Vector<Real> kshear1(3);
-  Vector<Real> kshear2(3);
-  kshear1.crossProduct(k, psi1);
-  kshear2.crossProduct(k, psi2);
+    Real phase_p = X.dot(kpush) - omega_p * current_time;
+    Real phase_s = X.dot(kpush) - omega_s * current_time;
 
-  const Real omega_p = knorm * cp;
-  const Real omega_s = knorm * cs;
+    vel =
+        A * (kpush * omega_p * cos(phase_p) + kshear * omega_s * cos(phase_s));
+  }
+};
 
-  Real phase_p = X.dot(kpush) - omega_p * current_time;
-  Real phase_s = X.dot(kpush) - omega_s * current_time;
+/* -------------------------------------------------------------------------- */
+template <> struct Verification<3> {
+  void displacement(Vector<Real> & disp, const Vector<Real> & coord,
+                    Real current_time) {
+    const auto & X = coord;
+    Vector<Real> kpush = k;
+    Vector<Real> kshear1(3);
+    Vector<Real> kshear2(3);
+    kshear1.crossProduct(k, psi1);
+    kshear2.crossProduct(k, psi2);
+
+    const Real omega_p = knorm * cp;
+    const Real omega_s = knorm * cs;
+
+    Real phase_p = X.dot(kpush) - omega_p * current_time;
+    Real phase_s = X.dot(kpush) - omega_s * current_time;
+
+    disp = A * (kpush * cos(phase_p) + kshear1 * cos(phase_s) +
+                kshear2 * cos(phase_s));
+  }
 
-  vel = A * (kpush * omega_p * cos(phase_p) + kshear1 * omega_s * cos(phase_s) +
+  void velocity(Vector<Real> & vel, const Vector<Real> & coord,
+                Real current_time) {
+    const auto & X = coord;
+    Vector<Real> kpush = k;
+    Vector<Real> kshear1(3);
+    Vector<Real> kshear2(3);
+    kshear1.crossProduct(k, psi1);
+    kshear2.crossProduct(k, psi2);
+
+    const Real omega_p = knorm * cp;
+    const Real omega_s = knorm * cs;
+
+    Real phase_p = X.dot(kpush) - omega_p * current_time;
+    Real phase_s = X.dot(kpush) - omega_s * current_time;
+
+    vel =
+        A * (kpush * omega_p * cos(phase_p) + kshear1 * omega_s * cos(phase_s) +
              kshear2 * omega_s * cos(phase_s));
+  }
 };
 
+/* -------------------------------------------------------------------------- */
 template <ElementType _type>
 class SolutionFunctor : public BC::Dirichlet::DirichletFunctor {
 public:
   SolutionFunctor(Real current_time, SolidMechanicsModel & model)
       : current_time(current_time), model(model) {}
 
 public:
-  // static constexpr UInt dim = DimensionHelper<_type>::dim;
   static constexpr UInt dim = ElementClass<_type>::getSpatialDimension();
 
   inline void operator()(UInt node, Vector<bool> & flags, Vector<Real> & primal,
                          const Vector<Real> & coord) const {
     flags(0) = true;
     auto & vel = model.getVelocity();
-    auto itVel = vel.begin(model.getSpatialDimension());
-    Vector<Real> v = itVel[node];
-    solution_disp<dim>(primal, coord, current_time);
-    solution_vel<dim>(v, coord, current_time);
+    auto it = vel.begin(model.getSpatialDimension());
+    Vector<Real> v = it[node];
+
+    Verification<dim> verif;
+    verif.displacement(primal, coord, current_time);
+    verif.velocity(v, coord, current_time);
   }
 
 private:
   Real current_time;
   SolidMechanicsModel & model;
 };
 
-template <ElementType _type, typename AM>
-void test_body(SolidMechanicsModel & model, AM analysis_method) {
-  // constexpr UInt dim = DimensionHelper<_type>::dim;
-  static constexpr UInt dim = ElementClass<_type>::getSpatialDimension();
+/* -------------------------------------------------------------------------- */
+// This fixture uses somewhat finer meshes representing bars.
+template <typename type_>
+class TestSMMFixtureBar
+    : public TestSMMFixture<std::tuple_element_t<0, type_>> {
+  using parent = TestSMMFixture<std::tuple_element_t<0, type_>>;
 
-  getStaticParser().parse("test_solid_mechanics_model_"
-                          "dynamics_material.dat");
-
-  model.initFull(SolidMechanicsModelOptions(analysis_method));
-
-  bool dump_paraview = false;
-
-  if (dump_paraview) {
-    std::stringstream base_name;
-    base_name << "bar" << analysis_method << _type;
-    model.setBaseName(base_name.str());
-    model.addDumpFieldVector("displacement");
-    model.addDumpField("mass");
-    model.addDumpField("velocity");
-    model.addDumpField("acceleration");
-    model.addDumpFieldVector("external_force");
-    model.addDumpFieldVector("internal_force");
-    model.addDumpField("stress");
-    model.addDumpField("strain");
-  }
+public:
+  void SetUp() override {
+    this->mesh_file = "bar" + aka::to_string(this->type) + ".msh";
+    parent::SetUp();
+
+    getStaticParser().parse("test_solid_mechanics_model_"
+                            "dynamics_material.dat");
+
+    auto analysis_method = std::tuple_element_t<1, type_>::value;
+    this->model->initFull(_analysis_method = analysis_method);
+
+    if (this->dump_paraview) {
+      std::stringstream base_name;
+      base_name << "bar" << analysis_method << this->type;
+      this->model->setBaseName(base_name.str());
+      this->model->addDumpFieldVector("displacement");
+      this->model->addDumpField("mass");
+      this->model->addDumpField("velocity");
+      this->model->addDumpField("acceleration");
+      this->model->addDumpFieldVector("external_force");
+      this->model->addDumpFieldVector("internal_force");
+      this->model->addDumpField("stress");
+      this->model->addDumpField("strain");
+    }
+
+    time_step = this->model->getStableTimeStep() / 10.;
+    this->model->setTimeStep(time_step);
+    // std::cout << "timestep: " << time_step << std::endl;
 
-  Real time_step = model.getStableTimeStep() / 10.;
-  model.setTimeStep(time_step);
-  std::cout << "timestep: " << time_step << std::endl;
+    const auto & position = this->mesh->getNodes();
+    auto & displacement = this->model->getDisplacement();
+    auto & velocity = this->model->getVelocity();
 
-  UInt nb_nodes = model.getMesh().getNbNodes();
-  UInt spatial_dimension = model.getSpatialDimension();
+    constexpr auto dim = parent::spatial_dimension;
 
-  auto & nodes = model.getMesh().getNodes();
-  auto & disp = model.getDisplacement();
-  auto & vel = model.getVelocity();
+    Verification<dim> verif;
 
-  Array<Real> disp_solution(nb_nodes, spatial_dimension);
+    for (auto && tuple :
+         zip(make_view(position, dim), make_view(displacement, dim),
+             make_view(velocity, dim))) {
+      verif.displacement(std::get<1>(tuple), std::get<0>(tuple), 0.);
+      verif.velocity(std::get<2>(tuple), std::get<0>(tuple), 0.);
+    }
+
+    if (dump_paraview)
+      this->model->dump();
+
+    /// boundary conditions
+    this->model->applyBC(SolutionFunctor<parent::type>(0., *this->model), "BC");
 
-  Real current_time = 0;
+    wave_velocity = 1.; // sqrt(E/rho) = sqrt(1/1) = 1
+    simulation_time = 5 / wave_velocity;
 
-  auto itNodes = nodes.begin(spatial_dimension);
-  auto itDisp = disp.begin(spatial_dimension);
-  auto itVel = vel.begin(spatial_dimension);
-  for (UInt n = 0; n < nb_nodes; ++n, ++itNodes, ++itDisp, ++itVel) {
-    solution_disp<dim>(*itDisp, *itNodes, current_time);
-    solution_vel<dim>(*itVel, *itNodes, current_time);
+    max_steps = simulation_time / time_step; // 100
+    auto ndump = 50;
+    dump_freq = max_steps / ndump;
   }
 
-  if (dump_paraview)
-    model.dump();
+protected:
+  Real time_step;
+  Real wave_velocity;
+  Real simulation_time;
+  UInt max_steps;
+  UInt dump_freq;
+  bool dump_paraview{false};
+};
 
-  /// boundary conditions
-  model.applyBC(SolutionFunctor<_type>(current_time, model), "BC");
+template <AnalysisMethod t>
+using analysis_method_t = std::integral_constant<AnalysisMethod, t>;
 
-  Real max_error = 0.;
-  Real wave_velocity = 1.; // sqrt(E/rho) = sqrt(1/1) = 1
-  Real simulation_time = 5 / wave_velocity;
+#ifdef AKANTU_IMPLICIT
+using TestAnalysisTypes =
+    std::tuple<analysis_method_t<_implicit_dynamic, _explicit_lumped_mass>>;
+#else
+using TestAnalysisTypes = std::tuple<analysis_method_t<_explicit_lumped_mass>>;
+#endif
 
-  UInt max_steps = simulation_time / time_step; // 100
-  UInt ndump = 50;
-  UInt dump_freq = max_steps / ndump;
+using TestTypes =
+    gtest_list_t<cross_product_t<TestElementTypes, TestAnalysisTypes>>;
 
-  std::cout << "max_steps: " << max_steps << std::endl;
+TYPED_TEST_CASE(TestSMMFixtureBar, TestTypes);
 
-  for (UInt s = 0; s < max_steps; ++s, current_time += time_step) {
+/* -------------------------------------------------------------------------- */
+
+TYPED_TEST(TestSMMFixtureBar, DynamicsExplicit) {
+  constexpr auto dim = TestFixture::spatial_dimension;
+  Real current_time = 0.;
+  const auto & position = this->mesh->getNodes();
+  const auto & displacement = this->model->getDisplacement();
+  UInt nb_nodes = this->mesh->getNbNodes();
+  UInt nb_global_nodes = this->mesh->getNbGlobalNodes();
+  Real max_error{0.};
 
-    if (s % dump_freq == 0 && dump_paraview)
-      model.dump();
+  Array<Real> displacement_solution(nb_nodes, dim);
+
+  Verification<dim> verif;
+
+  for (UInt s = 0; s < this->max_steps; ++s, current_time += this->time_step) {
+    if (s % this->dump_freq == 0 && this->dump_paraview)
+      this->model->dump();
 
     /// boundary conditions
-    model.applyBC(SolutionFunctor<_type>(current_time, model), "BC");
+    this->model->applyBC(
+        SolutionFunctor<TestFixture::type>(current_time, *this->model), "BC");
 
     // compute the disp solution
-    auto itDispSolution = disp_solution.begin(spatial_dimension);
-    itNodes = nodes.begin(spatial_dimension);
-    for (UInt n = 0; n < nb_nodes; ++n, ++itNodes, ++itDispSolution) {
-      solution_disp<dim>(*itDispSolution, *itNodes, current_time);
+    for (auto && tuple :
+         zip(make_view(position, dim), make_view(displacement_solution, dim))) {
+      verif.displacement(std::get<1>(tuple), std::get<0>(tuple), current_time);
     }
+
     // compute the error solution
-    itDispSolution = disp_solution.begin(spatial_dimension);
-    itDisp = disp.begin(spatial_dimension);
     Real disp_error = 0.;
-    for (UInt n = 0; n < nb_nodes; ++n, ++itDispSolution, ++itDisp) {
-      auto diff = *itDispSolution - *itDisp;
-
-      for (UInt i = 0; i < spatial_dimension; ++i) {
-        disp_error += diff(i) * diff(i);
-      }
+    for (auto && tuple : zip(make_view(displacement, dim),
+                             make_view(displacement_solution, dim))) {
+      auto diff = std::get<1>(tuple) - std::get<0>(tuple);
+      disp_error += diff.dot(diff);
     }
-    disp_error = sqrt(disp_error) / nb_nodes;
+
+    this->mesh->getCommunicator().allReduce(disp_error,
+                                            SynchronizerOperation::_sum);
+
+    disp_error = sqrt(disp_error) / nb_global_nodes;
     max_error = std::max(disp_error, max_error);
-    ASSERT_NEAR(disp_error, 0., 1e-3);
-    model.solveStep();
-  }
-  std::cout << "max error: " << max_error << std::endl;
-}
 
-#ifdef AKANTU_IMPLICIT
-TYPED_TEST(TestSMMFixtureBar, DynamicsImplicit) {
-  test_body<TestFixture::type>(*(this->model), _implicit_dynamic);
-}
-#endif
+    ASSERT_NEAR(disp_error, 0., 1e-3);
 
-TYPED_TEST(TestSMMFixtureBar, DynamicsExplicit) {
-  test_body<TestFixture::type>(*(this->model), _explicit_lumped_mass);
+    this->model->solveStep();
+  }
+  // std::cout << "max error: " << max_error << std::endl;
 }
 }
diff --git a/test/test_model/test_solid_mechanics_model/test_solid_mechanics_model_fixture.hh b/test/test_model/test_solid_mechanics_model/test_solid_mechanics_model_fixture.hh
index beef6ad66..431a03c94 100644
--- a/test/test_model/test_solid_mechanics_model/test_solid_mechanics_model_fixture.hh
+++ b/test/test_model/test_solid_mechanics_model/test_solid_mechanics_model_fixture.hh
@@ -1,63 +1,61 @@
 /* -------------------------------------------------------------------------- */
 #include "solid_mechanics_model.hh"
 #include "test_gtest_utils.hh"
+#include "communicator.hh"
 /* -------------------------------------------------------------------------- */
 #include <gtest/gtest.h>
 #include <vector>
 /* -------------------------------------------------------------------------- */
 
 #ifndef __AKANTU_TEST_SOLID_MECHANICS_MODEL_FIXTURE_HH__
 #define __AKANTU_TEST_SOLID_MECHANICS_MODEL_FIXTURE_HH__
 
 using namespace akantu;
 
 // This fixture uses very small meshes with a volume of 1.
 template <typename type_> class TestSMMFixture : public ::testing::Test {
 public:
   static constexpr ElementType type = type_::value;
   static constexpr size_t spatial_dimension =
       ElementClass<type>::getSpatialDimension();
 
   void SetUp() override {
     mesh = std::make_unique<Mesh>(this->spatial_dimension);
 
-    mesh->read(this->mesh_file);
+#if defined(AKANTU_PARALLEL)
+    if(Communicator::getStaticCommunicator().whoAmI() == 0) {
+#endif
+
+      mesh->read(this->mesh_file);
+
+#if defined(AKANTU_PARALLEL)
+    }
+
+    mesh->distribute();
+#endif
 
     SCOPED_TRACE(aka::to_string(this->type).c_str());
 
     model = std::make_unique<SolidMechanicsModel>(*mesh, _all_dimensions,
                                                   aka::to_string(this->type));
   }
 
   void TearDown() override {
     model.reset(nullptr);
     mesh.reset(nullptr);
   }
 
 protected:
   std::string mesh_file{aka::to_string(this->type) + ".msh"};
   std::unique_ptr<Mesh> mesh;
   std::unique_ptr<SolidMechanicsModel> model;
 };
 
 template <typename type_> constexpr ElementType TestSMMFixture<type_>::type;
 template <typename type_> constexpr size_t TestSMMFixture<type_>::spatial_dimension;
 
-using types = gtest_list_t<TestElementTypes>;
-
-TYPED_TEST_CASE(TestSMMFixture, types);
-
-
-// This fixture uses somewhat finer meshes representing bars.
-template <typename type_>
-class TestSMMFixtureBar : public TestSMMFixture<type_> {
-public:
-  void SetUp() override {
-    this->mesh_file = "bar" + aka::to_string(this->type) + ".msh";
-    TestSMMFixture<type_>::SetUp();
-  }
-};
+using gtest_element_types = gtest_list_t<TestElementTypes>;
 
-TYPED_TEST_CASE(TestSMMFixtureBar, types);
+TYPED_TEST_CASE(TestSMMFixture, gtest_element_types);
 
 #endif /* __AKANTU_TEST_SOLID_MECHANICS_MODEL_FIXTURE_HH__ */