diff --git a/test/test_model/test_solid_mechanics_model/test_materials/test_elastic_materials.cc b/test/test_model/test_solid_mechanics_model/test_materials/test_elastic_materials.cc
index 7b6ede457..1f6048cc8 100644
--- a/test/test_model/test_solid_mechanics_model/test_materials/test_elastic_materials.cc
+++ b/test/test_model/test_solid_mechanics_model/test_materials/test_elastic_materials.cc
@@ -1,919 +1,1064 @@
 /* -------------------------------------------------------------------------- */
 #include "material_elastic.hh"
 #include "material_elastic_orthotropic.hh"
 #include "solid_mechanics_model.hh"
 #include "test_material_fixtures.hh"
 /* -------------------------------------------------------------------------- */
 #include <gtest/gtest.h>
 #include <type_traits>
 /* -------------------------------------------------------------------------- */
 
 using namespace akantu;
 
 using types =
     ::testing::Types<Traits<MaterialElastic, 1>, Traits<MaterialElastic, 2>,
                      Traits<MaterialElastic, 3>,
 
                      Traits<MaterialElasticOrthotropic, 2>,
                      Traits<MaterialElasticOrthotropic, 3>,
 
                      Traits<MaterialElasticLinearAnisotropic, 2>,
                      Traits<MaterialElasticLinearAnisotropic, 3>>;
 
 /* -------------------------------------------------------------------------- */
 template <> void FriendMaterial<MaterialElastic<1>>::testComputeStress() {
   Real E = 3.;
   setParam("E", E);
 
   Matrix<Real> eps = {{2}};
   Matrix<Real> sigma(1, 1);
   Real sigma_th = 2;
   this->computeStressOnQuad(eps, sigma, sigma_th);
 
   auto solution = E * eps(0, 0) + sigma_th;
   ASSERT_NEAR(sigma(0, 0), solution, 1e-14);
 }
 
 /* -------------------------------------------------------------------------- */
 template <> void FriendMaterial<MaterialElastic<1>>::testEnergyDensity() {
   Real eps = 2, sigma = 2;
   Real epot = 0;
   this->computePotentialEnergyOnQuad({{eps}}, {{sigma}}, epot);
   Real solution = 2;
   ASSERT_NEAR(epot, solution, 1e-14);
 }
 
 /* -------------------------------------------------------------------------- */
 template <>
 void FriendMaterial<MaterialElastic<1>>::testComputeTangentModuli() {
   Real E = 2;
   setParam("E", E);
   Matrix<Real> tangent(1, 1);
   this->computeTangentModuliOnQuad(tangent);
   ASSERT_NEAR(tangent(0, 0), E, 1e-14);
 }
 
 /* -------------------------------------------------------------------------- */
 template <> void FriendMaterial<MaterialElastic<1>>::testCelerity() {
   Real E = 3., rho = 2.;
   setParam("E", E);
   setParam("rho", rho);
 
   auto wave_speed = this->getCelerity(Element());
   auto solution = std::sqrt(E / rho);
   ASSERT_NEAR(wave_speed, solution, 1e-14);
 }
 
 /* -------------------------------------------------------------------------- */
 template <> void FriendMaterial<MaterialElastic<2>>::testComputeStress() {
   Real E = 1.;
   Real nu = .3;
   Real sigma_th = 0.3; // thermal stress
   setParam("E", E);
   setParam("nu", nu);
 
   Matrix<Real> rotation_matrix = getRandomRotation2d();
 
   auto grad_u = this->getDeviatoricStrain(1.).block(0, 0, 2, 2);
 
   auto grad_u_rot = this->applyRotation(grad_u, rotation_matrix);
 
   Matrix<Real> sigma_rot(2, 2);
   this->computeStressOnQuad(grad_u_rot, sigma_rot, sigma_th);
 
   auto sigma = this->reverseRotation(sigma_rot, rotation_matrix);
 
   Matrix<Real> identity(2, 2);
   identity.eye();
 
   Matrix<Real> sigma_expected =
       0.5 * E / (1 + nu) * (grad_u + grad_u.transpose()) + sigma_th * identity;
 
   auto diff = sigma - sigma_expected;
   Real stress_error = diff.norm<L_inf>();
   ASSERT_NEAR(stress_error, 0., 1e-14);
 }
 
 /* -------------------------------------------------------------------------- */
 template <> void FriendMaterial<MaterialElastic<2>>::testEnergyDensity() {
   Matrix<Real> sigma = {{1, 2}, {2, 4}};
   Matrix<Real> eps = {{1, 0}, {0, 1}};
   Real epot = 0;
   Real solution = 2.5;
   this->computePotentialEnergyOnQuad(eps, sigma, epot);
   ASSERT_NEAR(epot, solution, 1e-14);
 }
 
 /* -------------------------------------------------------------------------- */
 template <>
 void FriendMaterial<MaterialElastic<2>>::testComputeTangentModuli() {
   Real E = 1.;
   Real nu = .3;
   setParam("E", E);
   setParam("nu", nu);
   Matrix<Real> tangent(3, 3);
 
   /* Plane Strain */
   // clang-format off
   Matrix<Real> solution = {
     {1 - nu, nu, 0},
     {nu, 1 - nu, 0},
     {0, 0, (1 - 2 * nu) / 2},
   };
   // clang-format on
   solution *= E / ((1 + nu) * (1 - 2 * nu));
 
   this->computeTangentModuliOnQuad(tangent);
   Real tangent_error = (tangent - solution).norm<L_2>();
   ASSERT_NEAR(tangent_error, 0, 1e-14);
 
   /* Plane Stress */
   this->plane_stress = true;
   this->updateInternalParameters();
   // clang-format off
   solution = {
     {1, nu, 0},
     {nu, 1, 0},
     {0, 0, (1 - nu) / 2},
   };
   // clang-format on
   solution *= E / (1 - nu * nu);
 
   this->computeTangentModuliOnQuad(tangent);
   tangent_error = (tangent - solution).norm<L_2>();
   ASSERT_NEAR(tangent_error, 0, 1e-14);
 }
 
 /* -------------------------------------------------------------------------- */
 template <> void FriendMaterial<MaterialElastic<2>>::testCelerity() {
   Real E = 1.;
   Real nu = .3;
   Real rho = 2;
   setParam("E", E);
   setParam("nu", nu);
   setParam("rho", rho);
   auto push_wave_speed = this->getPushWaveSpeed(Element());
   auto celerity = this->getCelerity(Element());
 
   Real K = E / (3 * (1 - 2 * nu));
   Real mu = E / (2 * (1 + nu));
   Real sol = std::sqrt((K + 4. / 3 * mu) / rho);
 
   ASSERT_NEAR(push_wave_speed, sol, 1e-14);
   ASSERT_NEAR(celerity, sol, 1e-14);
 
   auto shear_wave_speed = this->getShearWaveSpeed(Element());
 
   sol = std::sqrt(mu / rho);
 
   ASSERT_NEAR(shear_wave_speed, sol, 1e-14);
 }
 
 /* -------------------------------------------------------------------------- */
 
 template <> void FriendMaterial<MaterialElastic<3>>::testComputeStress() {
   Real E = 1.;
   Real nu = .3;
   Real sigma_th = 0.3; // thermal stress
   setParam("E", E);
   setParam("nu", nu);
 
   Matrix<Real> rotation_matrix = getRandomRotation3d();
 
   auto grad_u = this->getDeviatoricStrain(1.);
 
   auto grad_u_rot = this->applyRotation(grad_u, rotation_matrix);
 
   Matrix<Real> sigma_rot(3, 3);
   this->computeStressOnQuad(grad_u_rot, sigma_rot, sigma_th);
 
   auto sigma = this->reverseRotation(sigma_rot, rotation_matrix);
 
   Matrix<Real> identity(3, 3);
   identity.eye();
 
   Matrix<Real> sigma_expected =
       0.5 * E / (1 + nu) * (grad_u + grad_u.transpose()) + sigma_th * identity;
 
   auto diff = sigma - sigma_expected;
   Real stress_error = diff.norm<L_inf>();
   ASSERT_NEAR(stress_error, 0., 1e-14);
 }
 
 /* -------------------------------------------------------------------------- */
 template <> void FriendMaterial<MaterialElastic<3>>::testEnergyDensity() {
   Matrix<Real> sigma = {{1, 2, 3}, {2, 4, 5}, {3, 5, 6}};
   Matrix<Real> eps = {{1, 0, 0}, {0, 1, 0}, {0, 0, 1}};
   Real epot = 0;
   Real solution = 5.5;
   this->computePotentialEnergyOnQuad(eps, sigma, epot);
   ASSERT_NEAR(epot, solution, 1e-14);
 }
 
 /* -------------------------------------------------------------------------- */
 template <>
 void FriendMaterial<MaterialElastic<3>>::testComputeTangentModuli() {
   Real E = 1.;
   Real nu = .3;
   setParam("E", E);
   setParam("nu", nu);
   Matrix<Real> tangent(6, 6);
 
   // clang-format off
   Matrix<Real> solution = {
       {1 - nu, nu, nu, 0, 0, 0},
       {nu, 1 - nu, nu, 0, 0, 0},
       {nu, nu, 1 - nu, 0, 0, 0},
       {0, 0, 0, (1 - 2 * nu) / 2, 0, 0},
       {0, 0, 0, 0, (1 - 2 * nu) / 2, 0},
       {0, 0, 0, 0, 0, (1 - 2 * nu) / 2},
   };
   // clang-format on
   solution *= E / ((1 + nu) * (1 - 2 * nu));
 
   this->computeTangentModuliOnQuad(tangent);
   Real tangent_error = (tangent - solution).norm<L_2>();
   ASSERT_NEAR(tangent_error, 0, 1e-14);
 }
 
 /* -------------------------------------------------------------------------- */
 template <> void FriendMaterial<MaterialElastic<3>>::testCelerity() {
   Real E = 1.;
   Real nu = .3;
   Real rho = 2;
   setParam("E", E);
   setParam("nu", nu);
   setParam("rho", rho);
 
   auto push_wave_speed = this->getPushWaveSpeed(Element());
   auto celerity = this->getCelerity(Element());
 
   Real K = E / (3 * (1 - 2 * nu));
   Real mu = E / (2 * (1 + nu));
   Real sol = std::sqrt((K + 4. / 3 * mu) / rho);
 
   ASSERT_NEAR(push_wave_speed, sol, 1e-14);
   ASSERT_NEAR(celerity, sol, 1e-14);
 
   auto shear_wave_speed = this->getShearWaveSpeed(Element());
 
   sol = std::sqrt(mu / rho);
 
   ASSERT_NEAR(shear_wave_speed, sol, 1e-14);
 }
 
 /* -------------------------------------------------------------------------- */
 template <>
 void FriendMaterial<MaterialElasticOrthotropic<2>>::testComputeStress() {
   UInt Dim = 2;
   Real E1 = 1.;
   Real E2 = 2.;
   Real nu12 = 0.1;
   Real G12 = 2.;
 
   setParamNoUpdate("E1", E1);
   setParamNoUpdate("E2", E2);
   setParamNoUpdate("nu12", nu12);
   setParamNoUpdate("G12", G12);
 
   // material frame of reference is rotate by rotation_matrix starting from
   // canonical basis
   Matrix<Real> rotation_matrix = getRandomRotation2d();
 
   // canonical basis as expressed in the material frame of reference, as
   // required by MaterialElasticOrthotropic class (it is simply given by the
   // columns of the rotation_matrix; the lines give the material basis expressed
   // in the canonical frame of reference)
   Vector<Real> v1(Dim);
   Vector<Real> v2(Dim);
   for (UInt i = 0; i < Dim; ++i) {
     v1[i] = rotation_matrix(i, 0);
     v2[i] = rotation_matrix(i, 1);
   }
 
   setParamNoUpdate("n1", v1.normalize());
   setParamNoUpdate("n2", v2.normalize());
 
   // set internal Cijkl matrix expressed in the canonical frame of reference
   this->updateInternalParameters();
 
   // gradient in material frame of reference
   auto grad_u = (this->getDeviatoricStrain(2.) + this->getHydrostaticStrain(1.))
                     .block(0, 0, 2, 2);
 
   // gradient in canonical basis (we need to rotate *back* to the canonical
   // basis)
   auto grad_u_rot = this->reverseRotation(grad_u, rotation_matrix);
 
   // stress in the canonical basis
   Matrix<Real> sigma_rot(2, 2);
   this->computeStressOnQuad(grad_u_rot, sigma_rot);
 
   // stress in the material reference (we need to apply the rotation)
   auto sigma = this->applyRotation(sigma_rot, rotation_matrix);
 
   // construction of Cijkl engineering tensor in the *material* frame of
   // reference
   // ref: http://solidmechanics.org/Text/Chapter3_2/Chapter3_2.php#Sect3_2_13
   Real nu21 = nu12 * E2 / E1;
   Real gamma = 1 / (1 - nu12 * nu21);
 
   Matrix<Real> C_expected(2 * Dim, 2 * Dim, 0);
   C_expected(0, 0) = gamma * E1;
   C_expected(1, 1) = gamma * E2;
   C_expected(2, 2) = G12;
 
   C_expected(1, 0) = C_expected(0, 1) = gamma * E1 * nu21;
 
   // epsilon is computed directly in the *material* frame of reference
   Matrix<Real> epsilon = 0.5 * (grad_u + grad_u.transpose());
 
   // sigma_expected is computed directly in the *material* frame of reference
   Matrix<Real> sigma_expected(Dim, Dim);
   for (UInt i = 0; i < Dim; ++i) {
     for (UInt j = 0; j < Dim; ++j) {
       sigma_expected(i, i) += C_expected(i, j) * epsilon(j, j);
     }
   }
 
   sigma_expected(0, 1) = sigma_expected(1, 0) =
       C_expected(2, 2) * 2 * epsilon(0, 1);
 
   // sigmas are checked in the *material* frame of reference
   auto diff = sigma - sigma_expected;
   Real stress_error = diff.norm<L_inf>();
   ASSERT_NEAR(stress_error, 0., 1e-13);
 }
 
 /* -------------------------------------------------------------------------- */
 template <>
 void FriendMaterial<MaterialElasticOrthotropic<2>>::testEnergyDensity() {
   Matrix<Real> sigma = {{1, 2}, {2, 4}};
   Matrix<Real> eps = {{1, 0}, {0, 1}};
   Real epot = 0;
   Real solution = 2.5;
   this->computePotentialEnergyOnQuad(eps, sigma, epot);
   ASSERT_NEAR(epot, solution, 1e-14);
 }
 
 /* -------------------------------------------------------------------------- */
 template <>
 void FriendMaterial<MaterialElasticOrthotropic<2>>::testComputeTangentModuli() {
 
   // Note: for this test material and canonical basis coincide
   Vector<Real> n1 = {1, 0};
   Vector<Real> n2 = {0, 1};
   Real E1 = 1.;
   Real E2 = 2.;
   Real nu12 = 0.1;
   Real G12 = 2.;
 
   setParamNoUpdate("n1", n1);
   setParamNoUpdate("n2", n2);
   setParamNoUpdate("E1", E1);
   setParamNoUpdate("E2", E2);
   setParamNoUpdate("nu12", nu12);
   setParamNoUpdate("G12", G12);
 
   // set internal Cijkl matrix expressed in the canonical frame of reference
   this->updateInternalParameters();
 
   // construction of Cijkl engineering tensor in the *material* frame of
   // reference
   // ref: http://solidmechanics.org/Text/Chapter3_2/Chapter3_2.php#Sect3_2_13
   Real nu21 = nu12 * E2 / E1;
   Real gamma = 1 / (1 - nu12 * nu21);
 
   Matrix<Real> C_expected(3, 3);
   C_expected(0, 0) = gamma * E1;
   C_expected(1, 1) = gamma * E2;
   C_expected(2, 2) = G12;
 
   C_expected(1, 0) = C_expected(0, 1) = gamma * E1 * nu21;
 
   Matrix<Real> tangent(3, 3);
   this->computeTangentModuliOnQuad(tangent);
 
   Real tangent_error = (tangent - C_expected).norm<L_2>();
   ASSERT_NEAR(tangent_error, 0, 1e-14);
 }
 
+/* -------------------------------------------------------------------------- */
+
+template <> void FriendMaterial<MaterialElasticOrthotropic<2>>::testCelerity() {
+
+  // Note: for this test material and canonical basis coincide
+  Vector<Real> n1 = {1, 0};
+  Vector<Real> n2 = {0, 1};
+  Real E1 = 1.;
+  Real E2 = 2.;
+  Real nu12 = 0.1;
+  Real G12 = 2.;
+  Real rho = 2.5;
+
+  setParamNoUpdate("n1", n1);
+  setParamNoUpdate("n2", n2);
+  setParamNoUpdate("E1", E1);
+  setParamNoUpdate("E2", E2);
+  setParamNoUpdate("nu12", nu12);
+  setParamNoUpdate("G12", G12);
+  setParamNoUpdate("rho", rho);
+
+  // set internal Cijkl matrix expressed in the canonical frame of reference
+  this->updateInternalParameters();
+
+  // construction of Cijkl engineering tensor in the *material* frame of
+  // reference
+  // ref: http://solidmechanics.org/Text/Chapter3_2/Chapter3_2.php#Sect3_2_13
+  Real nu21 = nu12 * E2 / E1;
+  Real gamma = 1 / (1 - nu12 * nu21);
+
+  Matrix<Real> C_expected(3, 3);
+  C_expected(0, 0) = gamma * E1;
+  C_expected(1, 1) = gamma * E2;
+  C_expected(2, 2) = G12;
+
+  C_expected(1, 0) = C_expected(0, 1) = gamma * E1 * nu21;
+
+  Vector<Real> eig_expected(3);
+  C_expected.eig(eig_expected);
+
+  auto celerity_expected = std::sqrt(eig_expected(0) / rho);
+
+  auto celerity = this->getCelerity(Element());
+
+  ASSERT_NEAR(celerity_expected, celerity, 1e-14);
+}
+
 /* -------------------------------------------------------------------------- */
 template <>
 void FriendMaterial<MaterialElasticOrthotropic<3>>::testComputeStress() {
   UInt Dim = 3;
   Real E1 = 1.;
   Real E2 = 2.;
   Real E3 = 3.;
   Real nu12 = 0.1;
   Real nu13 = 0.2;
   Real nu23 = 0.3;
   Real G12 = 2.;
   Real G13 = 3.;
   Real G23 = 1.;
 
   setParamNoUpdate("E1", E1);
   setParamNoUpdate("E2", E2);
   setParamNoUpdate("E3", E3);
   setParamNoUpdate("nu12", nu12);
   setParamNoUpdate("nu13", nu13);
   setParamNoUpdate("nu23", nu23);
   setParamNoUpdate("G12", G12);
   setParamNoUpdate("G13", G13);
   setParamNoUpdate("G23", G23);
 
   // material frame of reference is rotate by rotation_matrix starting from
   // canonical basis
   Matrix<Real> rotation_matrix = getRandomRotation3d();
 
   // canonical basis as expressed in the material frame of reference, as
   // required by MaterialElasticOrthotropic class (it is simply given by the
   // columns of the rotation_matrix; the lines give the material basis expressed
   // in the canonical frame of reference)
   Vector<Real> v1(Dim);
   Vector<Real> v2(Dim);
   Vector<Real> v3(Dim);
   for (UInt i = 0; i < Dim; ++i) {
     v1[i] = rotation_matrix(i, 0);
     v2[i] = rotation_matrix(i, 1);
     v3[i] = rotation_matrix(i, 2);
   }
 
   setParamNoUpdate("n1", v1.normalize());
   setParamNoUpdate("n2", v2.normalize());
   setParamNoUpdate("n3", v3.normalize());
 
   // set internal Cijkl matrix expressed in the canonical frame of reference
   this->updateInternalParameters();
 
   // gradient in material frame of reference
   auto grad_u = this->getDeviatoricStrain(2.) + this->getHydrostaticStrain(1.);
 
   // gradient in canonical basis (we need to rotate *back* to the canonical
   // basis)
   auto grad_u_rot = this->reverseRotation(grad_u, rotation_matrix);
 
   // stress in the canonical basis
   Matrix<Real> sigma_rot(3, 3);
   this->computeStressOnQuad(grad_u_rot, sigma_rot);
 
   // stress in the material reference (we need to apply the rotation)
   auto sigma = this->applyRotation(sigma_rot, rotation_matrix);
 
   // construction of Cijkl engineering tensor in the *material* frame of
   // reference
   // ref: http://solidmechanics.org/Text/Chapter3_2/Chapter3_2.php#Sect3_2_13
   Real nu21 = nu12 * E2 / E1;
   Real nu31 = nu13 * E3 / E1;
   Real nu32 = nu23 * E3 / E2;
   Real gamma = 1 / (1 - nu12 * nu21 - nu23 * nu32 - nu31 * nu13 -
                     2 * nu21 * nu32 * nu13);
 
   Matrix<Real> C_expected(6, 6);
   C_expected(0, 0) = gamma * E1 * (1 - nu23 * nu32);
   C_expected(1, 1) = gamma * E2 * (1 - nu13 * nu31);
   C_expected(2, 2) = gamma * E3 * (1 - nu12 * nu21);
 
   C_expected(1, 0) = C_expected(0, 1) = gamma * E1 * (nu21 + nu31 * nu23);
   C_expected(2, 0) = C_expected(0, 2) = gamma * E1 * (nu31 + nu21 * nu32);
   C_expected(2, 1) = C_expected(1, 2) = gamma * E2 * (nu32 + nu12 * nu31);
 
   C_expected(3, 3) = G23;
   C_expected(4, 4) = G13;
   C_expected(5, 5) = G12;
 
   // epsilon is computed directly in the *material* frame of reference
   Matrix<Real> epsilon = 0.5 * (grad_u + grad_u.transpose());
 
   // sigma_expected is computed directly in the *material* frame of reference
   Matrix<Real> sigma_expected(Dim, Dim);
   for (UInt i = 0; i < Dim; ++i) {
     for (UInt j = 0; j < Dim; ++j) {
       sigma_expected(i, i) += C_expected(i, j) * epsilon(j, j);
     }
   }
 
   sigma_expected(0, 1) = C_expected(5, 5) * 2 * epsilon(0, 1);
   sigma_expected(0, 2) = C_expected(4, 4) * 2 * epsilon(0, 2);
   sigma_expected(1, 2) = C_expected(3, 3) * 2 * epsilon(1, 2);
   sigma_expected(1, 0) = sigma_expected(0, 1);
   sigma_expected(2, 0) = sigma_expected(0, 2);
   sigma_expected(2, 1) = sigma_expected(1, 2);
 
   // sigmas are checked in the *material* frame of reference
   auto diff = sigma - sigma_expected;
   Real stress_error = diff.norm<L_inf>();
   ASSERT_NEAR(stress_error, 0., 1e-13);
 }
 
 /* -------------------------------------------------------------------------- */
 template <>
 void FriendMaterial<MaterialElasticOrthotropic<3>>::testEnergyDensity() {
   Matrix<Real> sigma = {{1, 2, 3}, {2, 4, 5}, {3, 5, 6}};
   Matrix<Real> eps = {{1, 0, 0}, {0, 1, 0}, {0, 0, 1}};
   Real epot = 0;
   Real solution = 5.5;
   this->computePotentialEnergyOnQuad(eps, sigma, epot);
   ASSERT_NEAR(epot, solution, 1e-14);
 }
 
 /* -------------------------------------------------------------------------- */
 template <>
 void FriendMaterial<MaterialElasticOrthotropic<3>>::testComputeTangentModuli() {
 
   // Note: for this test material and canonical basis coincide
   UInt Dim = 3;
   Vector<Real> n1 = {1, 0, 0};
   Vector<Real> n2 = {0, 1, 0};
   Vector<Real> n3 = {0, 0, 1};
   Real E1 = 1.;
   Real E2 = 2.;
   Real E3 = 3.;
   Real nu12 = 0.1;
   Real nu13 = 0.2;
   Real nu23 = 0.3;
   Real G12 = 2.;
   Real G13 = 3.;
   Real G23 = 1.;
 
   setParamNoUpdate("n1", n1);
   setParamNoUpdate("n2", n2);
   setParamNoUpdate("n3", n3);
   setParamNoUpdate("E1", E1);
   setParamNoUpdate("E2", E2);
   setParamNoUpdate("E3", E3);
   setParamNoUpdate("nu12", nu12);
   setParamNoUpdate("nu13", nu13);
   setParamNoUpdate("nu23", nu23);
   setParamNoUpdate("G12", G12);
   setParamNoUpdate("G13", G13);
   setParamNoUpdate("G23", G23);
 
   // set internal Cijkl matrix expressed in the canonical frame of reference
   this->updateInternalParameters();
 
   // construction of Cijkl engineering tensor in the *material* frame of
   // reference
   // ref: http://solidmechanics.org/Text/Chapter3_2/Chapter3_2.php#Sect3_2_13
   Real nu21 = nu12 * E2 / E1;
   Real nu31 = nu13 * E3 / E1;
   Real nu32 = nu23 * E3 / E2;
   Real gamma = 1 / (1 - nu12 * nu21 - nu23 * nu32 - nu31 * nu13 -
                     2 * nu21 * nu32 * nu13);
 
   Matrix<Real> C_expected(2 * Dim, 2 * Dim, 0);
   C_expected(0, 0) = gamma * E1 * (1 - nu23 * nu32);
   C_expected(1, 1) = gamma * E2 * (1 - nu13 * nu31);
   C_expected(2, 2) = gamma * E3 * (1 - nu12 * nu21);
 
   C_expected(1, 0) = C_expected(0, 1) = gamma * E1 * (nu21 + nu31 * nu23);
   C_expected(2, 0) = C_expected(0, 2) = gamma * E1 * (nu31 + nu21 * nu32);
   C_expected(2, 1) = C_expected(1, 2) = gamma * E2 * (nu32 + nu12 * nu31);
 
   C_expected(3, 3) = G23;
   C_expected(4, 4) = G13;
   C_expected(5, 5) = G12;
 
   Matrix<Real> tangent(6, 6);
   this->computeTangentModuliOnQuad(tangent);
 
   Real tangent_error = (tangent - C_expected).norm<L_2>();
   ASSERT_NEAR(tangent_error, 0, 1e-14);
 }
 
+/* -------------------------------------------------------------------------- */
+template <> void FriendMaterial<MaterialElasticOrthotropic<3>>::testCelerity() {
+
+  // Note: for this test material and canonical basis coincide
+  UInt Dim = 3;
+  Vector<Real> n1 = {1, 0, 0};
+  Vector<Real> n2 = {0, 1, 0};
+  Vector<Real> n3 = {0, 0, 1};
+  Real E1 = 1.;
+  Real E2 = 2.;
+  Real E3 = 3.;
+  Real nu12 = 0.1;
+  Real nu13 = 0.2;
+  Real nu23 = 0.3;
+  Real G12 = 2.;
+  Real G13 = 3.;
+  Real G23 = 1.;
+  Real rho = 2.3;
+
+  setParamNoUpdate("n1", n1);
+  setParamNoUpdate("n2", n2);
+  setParamNoUpdate("n3", n3);
+  setParamNoUpdate("E1", E1);
+  setParamNoUpdate("E2", E2);
+  setParamNoUpdate("E3", E3);
+  setParamNoUpdate("nu12", nu12);
+  setParamNoUpdate("nu13", nu13);
+  setParamNoUpdate("nu23", nu23);
+  setParamNoUpdate("G12", G12);
+  setParamNoUpdate("G13", G13);
+  setParamNoUpdate("G23", G23);
+  setParamNoUpdate("rho", rho);
+
+  // set internal Cijkl matrix expressed in the canonical frame of reference
+  this->updateInternalParameters();
+
+  // construction of Cijkl engineering tensor in the *material* frame of
+  // reference
+  // ref: http://solidmechanics.org/Text/Chapter3_2/Chapter3_2.php#Sect3_2_13
+  Real nu21 = nu12 * E2 / E1;
+  Real nu31 = nu13 * E3 / E1;
+  Real nu32 = nu23 * E3 / E2;
+  Real gamma = 1 / (1 - nu12 * nu21 - nu23 * nu32 - nu31 * nu13 -
+                    2 * nu21 * nu32 * nu13);
+
+  Matrix<Real> C_expected(2 * Dim, 2 * Dim, 0);
+  C_expected(0, 0) = gamma * E1 * (1 - nu23 * nu32);
+  C_expected(1, 1) = gamma * E2 * (1 - nu13 * nu31);
+  C_expected(2, 2) = gamma * E3 * (1 - nu12 * nu21);
+
+  C_expected(1, 0) = C_expected(0, 1) = gamma * E1 * (nu21 + nu31 * nu23);
+  C_expected(2, 0) = C_expected(0, 2) = gamma * E1 * (nu31 + nu21 * nu32);
+  C_expected(2, 1) = C_expected(1, 2) = gamma * E2 * (nu32 + nu12 * nu31);
+
+  C_expected(3, 3) = G23;
+  C_expected(4, 4) = G13;
+  C_expected(5, 5) = G12;
+
+  Vector<Real> eig_expected(6);
+  C_expected.eig(eig_expected);
+
+  auto celerity_expected = std::sqrt(eig_expected(0) / rho);
+
+  auto celerity = this->getCelerity(Element());
+
+  ASSERT_NEAR(celerity_expected, celerity, 1e-14);
+}
+
 /* -------------------------------------------------------------------------- */
 template <>
 void FriendMaterial<MaterialElasticLinearAnisotropic<2>>::testComputeStress() {
   UInt Dim = 2;
   Matrix<Real> C = {
       {1.0, 0.3, 0.4}, {0.3, 2.0, 0.1}, {0.4, 0.1, 1.5},
   };
 
   setParamNoUpdate("C11", C(0, 0));
   setParamNoUpdate("C12", C(0, 1));
   setParamNoUpdate("C13", C(0, 2));
   setParamNoUpdate("C22", C(1, 1));
   setParamNoUpdate("C23", C(1, 2));
   setParamNoUpdate("C33", C(2, 2));
 
   // material frame of reference is rotate by rotation_matrix starting from
   // canonical basis
   Matrix<Real> rotation_matrix = getRandomRotation2d();
 
   // canonical basis as expressed in the material frame of reference, as
   // required by MaterialElasticLinearAnisotropic class (it is simply given by
   // the columns of the rotation_matrix; the lines give the material basis
   // expressed in the canonical frame of reference)
   Vector<Real> v1(Dim);
   Vector<Real> v2(Dim);
   for (UInt i = 0; i < Dim; ++i) {
     v1[i] = rotation_matrix(i, 0);
     v2[i] = rotation_matrix(i, 1);
   }
 
   setParamNoUpdate("n1", v1.normalize());
   setParamNoUpdate("n2", v2.normalize());
 
   // set internal Cijkl matrix expressed in the canonical frame of reference
   this->updateInternalParameters();
 
   // gradient in material frame of reference
   auto grad_u = (this->getDeviatoricStrain(2.) + this->getHydrostaticStrain(1.))
                     .block(0, 0, 2, 2);
 
   // gradient in canonical basis (we need to rotate *back* to the canonical
   // basis)
   auto grad_u_rot = this->reverseRotation(grad_u, rotation_matrix);
 
   // stress in the canonical basis
   Matrix<Real> sigma_rot(2, 2);
   this->computeStressOnQuad(grad_u_rot, sigma_rot);
 
   // stress in the material reference (we need to apply the rotation)
   auto sigma = this->applyRotation(sigma_rot, rotation_matrix);
 
   // epsilon is computed directly in the *material* frame of reference
   Matrix<Real> epsilon = 0.5 * (grad_u + grad_u.transpose());
   Vector<Real> epsilon_voigt(3);
   epsilon_voigt(0) = epsilon(0, 0);
   epsilon_voigt(1) = epsilon(1, 1);
   epsilon_voigt(2) = 2 * epsilon(0, 1);
 
   // sigma_expected is computed directly in the *material* frame of reference
   Vector<Real> sigma_voigt = C * epsilon_voigt;
   Matrix<Real> sigma_expected(Dim, Dim);
   sigma_expected(0, 0) = sigma_voigt(0);
   sigma_expected(1, 1) = sigma_voigt(1);
   sigma_expected(0, 1) = sigma_expected(1, 0) = sigma_voigt(2);
 
   // sigmas are checked in the *material* frame of reference
   auto diff = sigma - sigma_expected;
   Real stress_error = diff.norm<L_inf>();
   ASSERT_NEAR(stress_error, 0., 1e-13);
 }
 
 /* -------------------------------------------------------------------------- */
 template <>
 void FriendMaterial<MaterialElasticLinearAnisotropic<2>>::testEnergyDensity() {
   Matrix<Real> sigma = {{1, 2}, {2, 4}};
   Matrix<Real> eps = {{1, 0}, {0, 1}};
   Real epot = 0;
   Real solution = 2.5;
   this->computePotentialEnergyOnQuad(eps, sigma, epot);
   ASSERT_NEAR(epot, solution, 1e-14);
 }
 
 /* -------------------------------------------------------------------------- */
 template <>
 void FriendMaterial<
     MaterialElasticLinearAnisotropic<2>>::testComputeTangentModuli() {
 
   // Note: for this test material and canonical basis coincide
   Matrix<Real> C = {
       {1.0, 0.3, 0.4}, {0.3, 2.0, 0.1}, {0.4, 0.1, 1.5},
   };
 
   setParamNoUpdate("C11", C(0, 0));
   setParamNoUpdate("C12", C(0, 1));
   setParamNoUpdate("C13", C(0, 2));
   setParamNoUpdate("C22", C(1, 1));
   setParamNoUpdate("C23", C(1, 2));
   setParamNoUpdate("C33", C(2, 2));
 
   // set internal Cijkl matrix expressed in the canonical frame of reference
   this->updateInternalParameters();
 
   Matrix<Real> tangent(3, 3);
   this->computeTangentModuliOnQuad(tangent);
 
   Real tangent_error = (tangent - C).norm<L_2>();
   ASSERT_NEAR(tangent_error, 0, 1e-14);
 }
 
+/* -------------------------------------------------------------------------- */
+template <>
+void FriendMaterial<MaterialElasticLinearAnisotropic<2>>::testCelerity() {
+
+  // Note: for this test material and canonical basis coincide
+  Matrix<Real> C = {
+      {1.0, 0.3, 0.4}, {0.3, 2.0, 0.1}, {0.4, 0.1, 1.5},
+  };
+
+  Real rho = 2.7;
+
+  setParamNoUpdate("C11", C(0, 0));
+  setParamNoUpdate("C12", C(0, 1));
+  setParamNoUpdate("C13", C(0, 2));
+  setParamNoUpdate("C22", C(1, 1));
+  setParamNoUpdate("C23", C(1, 2));
+  setParamNoUpdate("C33", C(2, 2));
+  setParamNoUpdate("rho", rho);
+
+  // set internal Cijkl matrix expressed in the canonical frame of reference
+  this->updateInternalParameters();
+
+  Vector<Real> eig_expected(3);
+  C.eig(eig_expected);
+
+  auto celerity_expected = std::sqrt(eig_expected(0) / rho);
+
+  auto celerity = this->getCelerity(Element());
+
+  ASSERT_NEAR(celerity_expected, celerity, 1e-14);
+}
+
 /* -------------------------------------------------------------------------- */
 template <>
 void FriendMaterial<MaterialElasticLinearAnisotropic<3>>::testComputeStress() {
   UInt Dim = 3;
   Matrix<Real> C = {
       {1.0, 0.3, 0.4, 0.3, 0.2, 0.1}, {0.3, 2.0, 0.1, 0.2, 0.3, 0.2},
       {0.4, 0.1, 1.5, 0.1, 0.4, 0.3}, {0.3, 0.2, 0.1, 2.4, 0.1, 0.4},
       {0.2, 0.3, 0.4, 0.1, 0.9, 0.1}, {0.1, 0.2, 0.3, 0.4, 0.1, 1.2},
   };
 
   setParamNoUpdate("C11", C(0, 0));
   setParamNoUpdate("C12", C(0, 1));
   setParamNoUpdate("C13", C(0, 2));
   setParamNoUpdate("C14", C(0, 3));
   setParamNoUpdate("C15", C(0, 4));
   setParamNoUpdate("C16", C(0, 5));
   setParamNoUpdate("C22", C(1, 1));
   setParamNoUpdate("C23", C(1, 2));
   setParamNoUpdate("C24", C(1, 3));
   setParamNoUpdate("C25", C(1, 4));
   setParamNoUpdate("C26", C(1, 5));
   setParamNoUpdate("C33", C(2, 2));
   setParamNoUpdate("C34", C(2, 3));
   setParamNoUpdate("C35", C(2, 4));
   setParamNoUpdate("C36", C(2, 5));
   setParamNoUpdate("C44", C(3, 3));
   setParamNoUpdate("C45", C(3, 4));
   setParamNoUpdate("C46", C(3, 5));
   setParamNoUpdate("C55", C(4, 4));
   setParamNoUpdate("C56", C(4, 5));
   setParamNoUpdate("C66", C(5, 5));
 
   // material frame of reference is rotate by rotation_matrix starting from
   // canonical basis
   Matrix<Real> rotation_matrix = getRandomRotation3d();
 
   // canonical basis as expressed in the material frame of reference, as
   // required by MaterialElasticLinearAnisotropic class (it is simply given by
   // the columns of the rotation_matrix; the lines give the material basis
   // expressed in the canonical frame of reference)
   Vector<Real> v1(Dim);
   Vector<Real> v2(Dim);
   Vector<Real> v3(Dim);
   for (UInt i = 0; i < Dim; ++i) {
     v1[i] = rotation_matrix(i, 0);
     v2[i] = rotation_matrix(i, 1);
     v3[i] = rotation_matrix(i, 2);
   }
 
   setParamNoUpdate("n1", v1.normalize());
   setParamNoUpdate("n2", v2.normalize());
   setParamNoUpdate("n3", v3.normalize());
 
   // set internal Cijkl matrix expressed in the canonical frame of reference
   this->updateInternalParameters();
 
   // gradient in material frame of reference
   auto grad_u = this->getDeviatoricStrain(2.) + this->getHydrostaticStrain(1.);
 
   // gradient in canonical basis (we need to rotate *back* to the canonical
   // basis)
   auto grad_u_rot = this->reverseRotation(grad_u, rotation_matrix);
 
   // stress in the canonical basis
   Matrix<Real> sigma_rot(3, 3);
   this->computeStressOnQuad(grad_u_rot, sigma_rot);
 
   // stress in the material reference (we need to apply the rotation)
   auto sigma = this->applyRotation(sigma_rot, rotation_matrix);
 
   // epsilon is computed directly in the *material* frame of reference
   Matrix<Real> epsilon = 0.5 * (grad_u + grad_u.transpose());
   Vector<Real> epsilon_voigt(6);
   epsilon_voigt(0) = epsilon(0, 0);
   epsilon_voigt(1) = epsilon(1, 1);
   epsilon_voigt(2) = epsilon(2, 2);
   epsilon_voigt(3) = 2 * epsilon(1, 2);
   epsilon_voigt(4) = 2 * epsilon(0, 2);
   epsilon_voigt(5) = 2 * epsilon(0, 1);
 
   // sigma_expected is computed directly in the *material* frame of reference
   Vector<Real> sigma_voigt = C * epsilon_voigt;
   Matrix<Real> sigma_expected(Dim, Dim);
   sigma_expected(0, 0) = sigma_voigt(0);
   sigma_expected(1, 1) = sigma_voigt(1);
   sigma_expected(2, 2) = sigma_voigt(2);
   sigma_expected(1, 2) = sigma_expected(2, 1) = sigma_voigt(3);
   sigma_expected(0, 2) = sigma_expected(2, 0) = sigma_voigt(4);
   sigma_expected(0, 1) = sigma_expected(1, 0) = sigma_voigt(5);
 
   // sigmas are checked in the *material* frame of reference
   auto diff = sigma - sigma_expected;
   Real stress_error = diff.norm<L_inf>();
   ASSERT_NEAR(stress_error, 0., 1e-13);
 }
 
 /* -------------------------------------------------------------------------- */
 template <>
 void FriendMaterial<MaterialElasticLinearAnisotropic<3>>::testEnergyDensity() {
   Matrix<Real> sigma = {{1, 2, 3}, {2, 4, 5}, {3, 5, 6}};
   Matrix<Real> eps = {{1, 0, 0}, {0, 1, 0}, {0, 0, 1}};
   Real epot = 0;
   Real solution = 5.5;
   this->computePotentialEnergyOnQuad(eps, sigma, epot);
   ASSERT_NEAR(epot, solution, 1e-14);
 }
 
 /* -------------------------------------------------------------------------- */
 template <>
 void FriendMaterial<
     MaterialElasticLinearAnisotropic<3>>::testComputeTangentModuli() {
 
   // Note: for this test material and canonical basis coincide
   Matrix<Real> C = {
       {1.0, 0.3, 0.4, 0.3, 0.2, 0.1}, {0.3, 2.0, 0.1, 0.2, 0.3, 0.2},
       {0.4, 0.1, 1.5, 0.1, 0.4, 0.3}, {0.3, 0.2, 0.1, 2.4, 0.1, 0.4},
       {0.2, 0.3, 0.4, 0.1, 0.9, 0.1}, {0.1, 0.2, 0.3, 0.4, 0.1, 1.2},
   };
 
   setParamNoUpdate("C11", C(0, 0));
   setParamNoUpdate("C12", C(0, 1));
   setParamNoUpdate("C13", C(0, 2));
   setParamNoUpdate("C14", C(0, 3));
   setParamNoUpdate("C15", C(0, 4));
   setParamNoUpdate("C16", C(0, 5));
   setParamNoUpdate("C22", C(1, 1));
   setParamNoUpdate("C23", C(1, 2));
   setParamNoUpdate("C24", C(1, 3));
   setParamNoUpdate("C25", C(1, 4));
   setParamNoUpdate("C26", C(1, 5));
   setParamNoUpdate("C33", C(2, 2));
   setParamNoUpdate("C34", C(2, 3));
   setParamNoUpdate("C35", C(2, 4));
   setParamNoUpdate("C36", C(2, 5));
   setParamNoUpdate("C44", C(3, 3));
   setParamNoUpdate("C45", C(3, 4));
   setParamNoUpdate("C46", C(3, 5));
   setParamNoUpdate("C55", C(4, 4));
   setParamNoUpdate("C56", C(4, 5));
   setParamNoUpdate("C66", C(5, 5));
 
   // set internal Cijkl matrix expressed in the canonical frame of reference
   this->updateInternalParameters();
 
   Matrix<Real> tangent(6, 6);
   this->computeTangentModuliOnQuad(tangent);
 
   Real tangent_error = (tangent - C).norm<L_2>();
   ASSERT_NEAR(tangent_error, 0, 1e-14);
 }
 
 /* -------------------------------------------------------------------------- */
-template <> void FriendMaterial<MaterialElasticLinearAnisotropic<3>>::testCelerity() {
+template <>
+void FriendMaterial<MaterialElasticLinearAnisotropic<3>>::testCelerity() {
 
   // Note: for this test material and canonical basis coincide
   Matrix<Real> C = {
-    {1.0, 0.3, 0.4, 0.3, 0.2, 0.1},
-    {0.3, 2.0, 0.1, 0.2, 0.3, 0.2},
-    {0.4, 0.1, 1.5, 0.1, 0.4, 0.3},
-    {0.3, 0.2, 0.1, 2.4, 0.1, 0.4},
-    {0.2, 0.3, 0.4, 0.1, 0.9, 0.1},
-    {0.1, 0.2, 0.3, 0.4, 0.1, 1.2},
+      {1.0, 0.3, 0.4, 0.3, 0.2, 0.1}, {0.3, 2.0, 0.1, 0.2, 0.3, 0.2},
+      {0.4, 0.1, 1.5, 0.1, 0.4, 0.3}, {0.3, 0.2, 0.1, 2.4, 0.1, 0.4},
+      {0.2, 0.3, 0.4, 0.1, 0.9, 0.1}, {0.1, 0.2, 0.3, 0.4, 0.1, 1.2},
   };
   Real rho = 2.9;
 
-  setParamNoUpdate("C11", C(0,0));
-  setParamNoUpdate("C12", C(0,1));
-  setParamNoUpdate("C13", C(0,2));
-  setParamNoUpdate("C14", C(0,3));
-  setParamNoUpdate("C15", C(0,4));
-  setParamNoUpdate("C16", C(0,5));
-  setParamNoUpdate("C22", C(1,1));
-  setParamNoUpdate("C23", C(1,2));
-  setParamNoUpdate("C24", C(1,3));
-  setParamNoUpdate("C25", C(1,4));
-  setParamNoUpdate("C26", C(1,5));
-  setParamNoUpdate("C33", C(2,2));
-  setParamNoUpdate("C34", C(2,3));
-  setParamNoUpdate("C35", C(2,4));
-  setParamNoUpdate("C36", C(2,5));
-  setParamNoUpdate("C44", C(3,3));
-  setParamNoUpdate("C45", C(3,4));
-  setParamNoUpdate("C46", C(3,5));
-  setParamNoUpdate("C55", C(4,4));
-  setParamNoUpdate("C56", C(4,5));
-  setParamNoUpdate("C66", C(5,5));
+  setParamNoUpdate("C11", C(0, 0));
+  setParamNoUpdate("C12", C(0, 1));
+  setParamNoUpdate("C13", C(0, 2));
+  setParamNoUpdate("C14", C(0, 3));
+  setParamNoUpdate("C15", C(0, 4));
+  setParamNoUpdate("C16", C(0, 5));
+  setParamNoUpdate("C22", C(1, 1));
+  setParamNoUpdate("C23", C(1, 2));
+  setParamNoUpdate("C24", C(1, 3));
+  setParamNoUpdate("C25", C(1, 4));
+  setParamNoUpdate("C26", C(1, 5));
+  setParamNoUpdate("C33", C(2, 2));
+  setParamNoUpdate("C34", C(2, 3));
+  setParamNoUpdate("C35", C(2, 4));
+  setParamNoUpdate("C36", C(2, 5));
+  setParamNoUpdate("C44", C(3, 3));
+  setParamNoUpdate("C45", C(3, 4));
+  setParamNoUpdate("C46", C(3, 5));
+  setParamNoUpdate("C55", C(4, 4));
+  setParamNoUpdate("C56", C(4, 5));
+  setParamNoUpdate("C66", C(5, 5));
   setParamNoUpdate("rho", rho);
 
   // set internal Cijkl matrix expressed in the canonical frame of reference
   this->updateInternalParameters();
 
   Vector<Real> eig_expected(6);
   C.eig(eig_expected);
 
-  auto celerity_expected = std::sqrt(eig_expected(0)/rho);
+  auto celerity_expected = std::sqrt(eig_expected(0) / rho);
 
   auto celerity = this->getCelerity(Element());
 
   ASSERT_NEAR(celerity_expected, celerity, 1e-14);
 }
 
 /* -------------------------------------------------------------------------- */
 
 namespace {
 
 template <typename T>
 class TestElasticMaterialFixture : public ::TestMaterialFixture<T> {};
 
 TYPED_TEST_CASE(TestElasticMaterialFixture, types);
 
 TYPED_TEST(TestElasticMaterialFixture, ElasticComputeStress) {
   this->material->testComputeStress();
 }
 
 TYPED_TEST(TestElasticMaterialFixture, ElasticEnergyDensity) {
   this->material->testEnergyDensity();
 }
 
 TYPED_TEST(TestElasticMaterialFixture, ElasticComputeTangentModuli) {
   this->material->testComputeTangentModuli();
 }
 
 TYPED_TEST(TestElasticMaterialFixture, ElasticComputeCelerity) {
   this->material->testCelerity();
 }
 
 } // namespace