From 8ad2c792a4315b40fdbfdde6d65b9a05a4d50639 Mon Sep 17 00:00:00 2001
From: acrovato <170-acrovato@users.noreply.gitlab.uliege.be>
Date: Sat, 21 Mar 2020 21:35:47 +0100
Subject: [PATCH] Rewritten Element methods. @K.Liegeois work remains.

---
 mirrors/src/wSolver.cpp |  37 +++---
 tbox/src/wElement.cpp   |  17 +--
 tbox/src/wElement.h     |   7 +-
 tbox/src/wHex8.cpp      | 158 ++++++++++++------------
 tbox/src/wHex8.h        |   6 +-
 tbox/src/wLine2.cpp     |  55 ++++-----
 tbox/src/wMshDeform.cpp |   2 +-
 tbox/src/wQuad4.cpp     |  48 +++++---
 tbox/src/wTetra4.cpp    | 216 +++++++++++----------------------
 tbox/src/wTetra4.h      |   7 +-
 tbox/src/wTri3.cpp      | 260 ++++++++++++++++++----------------------
 tbox/src/wTri3.h        |   2 +-
 12 files changed, 355 insertions(+), 460 deletions(-)

diff --git a/mirrors/src/wSolver.cpp b/mirrors/src/wSolver.cpp
index 17c91fe4..d783dc87 100644
--- a/mirrors/src/wSolver.cpp
+++ b/mirrors/src/wSolver.cpp
@@ -161,23 +161,20 @@ void Solver::start(std::shared_ptr<MshExport> mshWriter)
             double E = m->E;
             double nu = m->nu;
 
-            double lambda = (nu * E) / ((1 + nu) * (1 - 2 * nu));
-            double G = E / (2 * (1 + nu));
-
-            Eigen::MatrixXd H = Eigen::MatrixXd::Zero(9, 9);
-
-            for (auto i = 0; i < 3; ++i)
-                for (auto j = 0; j < 3; ++j)
-                    for (auto k = 0; k < 3; ++k)
-                        for (auto l = 0; l < 3; ++l)
-                        {
-                            if (i == j && k == l)
-                                H(i * 3 + j, k * 3 + l) = lambda;
-                            if (i == k && j == l)
-                                H(i * 3 + j, k * 3 + l) = H(i * 3 + j, k * 3 + l) + G;
-                            if (i == l && j == k)
-                                H(i * 3 + j, k * 3 + l) = H(i * 3 + j, k * 3 + l) + G;
-                        }
+            Eigen::MatrixXd H = Eigen::MatrixXd::Zero(6, 6);
+            H(0, 0) = 1 - nu;
+            H(1, 1) = 1 - nu;
+            H(2, 2) = 1 - nu;
+            H(3, 3) = (1 - 2 * nu) / 2;
+            H(4, 4) = (1 - 2 * nu) / 2;
+            H(5, 5) = (1 - 2 * nu) / 2;
+            H(0, 1) = nu;
+            H(1, 0) = H(0, 1);
+            H(0, 2) = nu;
+            H(2, 0) = H(0, 2);
+            H(1, 2) = nu;
+            H(2, 1) = H(1, 2);
+            H *= E / ((1 + nu) * (1 - 2 * nu));
 
             // K matrix
             //=============================tbb==================================
@@ -192,7 +189,7 @@ void Solver::start(std::shared_ptr<MshExport> mshWriter)
                                  if (e->type() != ELTYPE::HEX8 && e->type() != ELTYPE::TETRA4)
                                      return; //if the element is not a tetrahedron or a hexahedron, it is not treated
 
-                                 e->buildK_mechanic(K_e, H);
+                                 e->buildK_mechanical(K_e, H);
 
                                  for (size_t ii = 0; ii < e->nodes.size(); ++ii)
                                  {
@@ -229,7 +226,7 @@ void Solver::start(std::shared_ptr<MshExport> mshWriter)
                 if (e->type() != ELTYPE::HEX8 && e->type() != ELTYPE::TETRA4)
                     return; //if the element is not a tetrahedron or a hexahedron, it is not treated
 
-                e->buildL_thermic(L_e, K_conductivity);
+                e->buildL_thermal(L_e, K_conductivity);
 
                 for (size_t ii = 0; ii < e->nodes.size(); ++ii)
                 {
@@ -271,7 +268,7 @@ void Solver::start(std::shared_ptr<MshExport> mshWriter)
                 if (e->type() != ELTYPE::HEX8 && e->type() != ELTYPE::TETRA4)
                     return; //if the element is not a tetrahedron or a hexahedron, it is not treated
 
-                e->buildS_thermomechanic(S_e, D);
+                e->buildS_thermomechanical(S_e, D);
 
                 for (size_t ii = 0; ii < e->nodes.size(); ++ii)
                 {
diff --git a/tbox/src/wElement.cpp b/tbox/src/wElement.cpp
index cabcb7a6..0105fcca 100644
--- a/tbox/src/wElement.cpp
+++ b/tbox/src/wElement.cpp
@@ -204,24 +204,19 @@ void Element::buildDK(Eigen::MatrixXd &K, std::vector<double> const &u, Fct0 con
     throw std::runtime_error("Element::buildNK not implemented\n");
 }
 //---------------------
-void Element::buildK_linElastic(Eigen::MatrixXd &K, Eigen::MatrixXd const &H)
+void Element::buildK_mechanical(Eigen::MatrixXd &K_e, Eigen::MatrixXd const &H)
 {
-    throw std::runtime_error("Element::buildK_linElastic not implemented\n");
+    throw std::runtime_error("Element::buildK_mechanical not implemented\n");
 }
 
-void Element::buildK_mechanic(Eigen::MatrixXd &K_e, Eigen::MatrixXd const &H)
+void Element::buildS_thermomechanical(Eigen::MatrixXd &S_e, Eigen::MatrixXd const &D)
 {
-    throw std::runtime_error("Element::buildK_mechanic not implemented\n");
+    throw std::runtime_error("Element::buildS_thermomechanical not implemented\n");
 }
 
-void Element::buildS_thermomechanic(Eigen::MatrixXd &S_e, Eigen::MatrixXd const &D)
+void Element::buildL_thermal(Eigen::MatrixXd &L_e, Eigen::MatrixXd const &C)
 {
-    throw std::runtime_error("Element::buildS_thermomechanic not implemented\n");
-}
-
-void Element::buildL_thermic(Eigen::MatrixXd &L_e, Eigen::MatrixXd const &K_conductivity)
-{
-    throw std::runtime_error("Element::buildL_thermic not implemented\n");
+    throw std::runtime_error("Element::buildL_thermial not implemented\n");
 }
 
 void Element::strain_stress(Eigen::MatrixXd &Strain, Eigen::MatrixXd &Stress, Eigen::MatrixXd const &H, std::vector<double> const &u)
diff --git a/tbox/src/wElement.h b/tbox/src/wElement.h
index c44114cb..51276571 100644
--- a/tbox/src/wElement.h
+++ b/tbox/src/wElement.h
@@ -92,10 +92,9 @@ public:
     virtual void buildK(Eigen::MatrixXd &K, std::vector<double> const &u, Fct2 const &fct, bool fake);
     virtual void buildDK(Eigen::MatrixXd &K, std::vector<double> const &u, Fct0 const &fct);
     //---------------------
-    virtual void buildK_linElastic(Eigen::MatrixXd &K, Eigen::MatrixXd const &H);
-    virtual void buildK_mechanic(Eigen::MatrixXd &K_e, Eigen::MatrixXd const &H);
-    virtual void buildS_thermomechanic(Eigen::MatrixXd &S_e, Eigen::MatrixXd const &D);
-    virtual void buildL_thermic(Eigen::MatrixXd &L_e, Eigen::MatrixXd const &K_conductivity);
+    virtual void buildK_mechanical(Eigen::MatrixXd &K_e, Eigen::MatrixXd const &H);
+    virtual void buildS_thermomechanical(Eigen::MatrixXd &S_e, Eigen::MatrixXd const &D);
+    virtual void buildL_thermal(Eigen::MatrixXd &L_e, Eigen::MatrixXd const &C);
     virtual void strain_stress(Eigen::MatrixXd &Strain, Eigen::MatrixXd &Stress, Eigen::MatrixXd const &H, std::vector<double> const &u);
     virtual void iso_coordinates(Pt x, double eta, double dzeta);
     virtual Pt normal();
diff --git a/tbox/src/wHex8.cpp b/tbox/src/wHex8.cpp
index d0597d61..2e33566d 100644
--- a/tbox/src/wHex8.cpp
+++ b/tbox/src/wHex8.cpp
@@ -36,7 +36,7 @@ Hex8::~Hex8()
         delete pmem;
 }
 
-/*
+/**
  * @brief Private memory handling Jacobian for Hex8 Element 
  * @authors Romain Boman, Adrien Crovato
  */
@@ -49,7 +49,7 @@ MemHex8 &Hex8::getMem()
     return *pmem;
 }
 
-/*
+/**
  * @brief Private cache handling shape functions and Gauss points for Hex8 
  * @authors Romain Boman, Adrien Crovato
  */
@@ -65,6 +65,8 @@ Cache &Hex8::getVCache()
 
 /**
  * @brief Compute Jacobian Matrix at Gauss point k
+ * 
+ * J_ij(3,3) = diN_n * xj_n (n is the node)
  * @authors Romain Boman
  */
 double Hex8::buildJ(size_t k, Eigen::MatrixXd &J) const
@@ -81,83 +83,78 @@ double Hex8::buildJ(size_t k, Eigen::MatrixXd &J) const
     return J.determinant();
 }
 
+/**
+ * @brief Compute stiffness matrix for scalar field
+ * 
+ * K_ij(8,8) = int f*dN_j*dN_i dV
+ * @authors Romain Boman
+ */
 void Hex8::buildK(Eigen::MatrixXd &K, std::vector<double> const &u, Fct0 const &fct)
 {
     CacheHex8 &cache = getCache();
     GaussHex8 &gauss = cache.gauss;
     MemHex8 &mem = getMem();
 
-    K = Eigen::MatrixXd::Zero(8, 8);
-    Eigen::Vector3d factor1;
-    Eigen::Vector3d factor2;
+    // Gauss integration
+    K = Eigen::Matrix<double, 8, 8>::Zero();
     for (size_t k = 0; k < gauss.p.size(); ++k)
     {
-        // function and Jacobian
-        double fk = fct.eval(*this, u, k);
-        double detJ = mem.getDetJ(k);
+        // Jacobian inverse and shape functions
         Eigen::Matrix3d const &J = mem.getJinv(k);
-
+        Eigen::Matrix<double, 3, 8> dN;
         for (size_t i = 0; i < nodes.size(); ++i)
-        {
-            std::vector<double> &dffi = cache.dff[k][i];
-            factor1 = J * Eigen::Vector3d(dffi.data());
+            dN.col(i) = Eigen::Vector3d(cache.dff[k][i].data());
 
-            for (size_t j = 0; j < nodes.size(); ++j)
-            {
-                std::vector<double> &dffj = cache.dff[k][j];
-                factor2 = J * Eigen::Vector3d(dffj.data());
-                K(i, j) += factor1.dot(factor2) * gauss.w[k] * detJ * fk;
-            }
-        }
+        // Elementary stiffness matrix
+        K += (J * dN).transpose() * J * dN * fct.eval(*this, u, k) * gauss.w[k] * mem.getDetJ(k);
     }
 }
 
-void Hex8::buildK_mechanic(Eigen::MatrixXd &K_e, Eigen::MatrixXd const &H)
+/**
+ * @brief Compute linear elasticity stiffness matrix
+ * 
+ * K_ij(24,24) = int eps_k H_ijkl eps_l dV = B(24,6)H(6,6)B(6,24)
+ * @authors Adrien Crovato
+ */
+void Hex8::buildK_mechanical(Eigen::MatrixXd &K, Eigen::MatrixXd const &H)
 {
     CacheHex8 &cache = getCache();
     GaussHex8 &gauss = cache.gauss;
     MemHex8 &mem = getMem();
 
-    K_e = Eigen::MatrixXd::Zero(24, 24);
-    Eigen::Vector3d factor1;
-    Eigen::Vector3d factor2;
-    Eigen::Vector3d factor3;
-    Eigen::Matrix3d TMP1;
-    for (size_t a = 0; a < gauss.p.size(); ++a)
+    K = Eigen::MatrixXd::Zero(24, 24);
+    for (size_t k = 0; k < gauss.p.size(); ++k)
     {
-        // calcul de la matrice jacobienne (au point de Gauss "ksi")
-        double detJ = mem.getDetJ(a);
-        Eigen::Matrix3d const &J = mem.getJinv(a);
-
-        // calcul de K (au point de Gauss "ksi")
+        // Jacobian inverse
+        Eigen::Matrix3d const &invJ = mem.getJinv(k);
+        // Fill B matrix (shape functions)
+        Eigen::MatrixXd B = Eigen::MatrixXd::Zero(6, 3 * nodes.size());
         for (size_t i = 0; i < nodes.size(); ++i)
         {
-            std::vector<double> &dffi = cache.dff[a][i];
-            factor1 = J * Eigen::Vector3d(dffi.data());
-
-            for (size_t j = i; j < nodes.size(); ++j)
-            {
-                std::vector<double> &dffj = cache.dff[a][j];
-                factor2 = J * Eigen::Vector3d(dffj.data());
-
-                for (size_t k = 0; k < 3; ++k)
-                    for (size_t m = 0; m < 3; ++m)
-                    {
-                        for (size_t l = 0; l < 3; ++l)
-                            for (size_t n = 0; n < 3; ++n)
-                                TMP1(l, n) = H(k * 3 + l, m * 3 + n);
-                        factor3 = TMP1 * factor2;
-                        K_e(i * 3 + k, j * 3 + m) += factor1.dot(factor3) * gauss.w[a] * detJ;
-                    }
-            }
+            // Compute [Ni,x Ni,y, Ni_z]
+            std::vector<double> &dffi = cache.dff[k][i];
+            Eigen::Vector3d dN = invJ * Eigen::Vector3d(dffi.data());
+            B(0, 3 * i) = dN(0);
+            B(1, 3 * i + 1) = dN(1);
+            B(2, 3 * i + 2) = dN(2);
+            B(3, 3 * i + 1) = dN(2);
+            B(3, 3 * i + 2) = dN(1);
+            B(4, 3 * i) = dN(2);
+            B(4, 3 * i + 2) = dN(0);
+            B(5, 3 * i) = dN(1);
+            B(5, 3 * i + 1) = dN(0);
         }
+
+        // Compute stiffness matrix
+        K += B.transpose() * H * B * gauss.w[k] * mem.getDetJ(k);
     }
-    for (size_t i = 0; i < 3 * nodes.size(); ++i)
-        for (size_t j = i; j < 3 * nodes.size(); ++j)
-            K_e(j, i) = K_e(i, j);
 }
 
-void Hex8::buildS_thermomechanic(Eigen::MatrixXd &S_e, Eigen::MatrixXd const &D)
+/**
+ * @brief Compute thermomecanical matrix
+ * @authors Kim Liegeois
+ */
+void Hex8::buildS_thermomechanical(Eigen::MatrixXd &S_e, Eigen::MatrixXd const &D)
 {
     CacheHex8 &cache = getCache();
     GaussHex8 &gauss = cache.gauss;
@@ -186,33 +183,33 @@ void Hex8::buildS_thermomechanic(Eigen::MatrixXd &S_e, Eigen::MatrixXd const &D)
     }
 }
 
-void Hex8::buildL_thermic(Eigen::MatrixXd &L_e, Eigen::MatrixXd const &K_conductivity)
+/**
+ * @brief Compute thermal matrix
+ * @authors Kim Liegeois
+ */
+void Hex8::buildL_thermal(Eigen::MatrixXd &L_e, Eigen::MatrixXd const &C)
 {
     CacheHex8 &cache = getCache();
     GaussHex8 &gauss = cache.gauss;
     MemHex8 &mem = getMem();
 
-    L_e = Eigen::MatrixXd::Zero(8, 8);
-    Eigen::Vector3d factor1;
-    Eigen::Vector3d factor2;
-    Eigen::Vector3d factor3;
+    // Gauss integration
+    L_e = Eigen::Matrix<double, 8, 8>::Zero();
     for (size_t a = 0; a < gauss.p.size(); ++a)
     {
-        // calcul de la matrice jacobienne (au point de Gauss "ksi")
+        // Jacobian
         double detJ = mem.getDetJ(a);
         Eigen::Matrix3d const &J = mem.getJinv(a);
 
-        // calcul de K (au point de Gauss "ksi")
         for (size_t i = 0; i < nodes.size(); ++i)
         {
             std::vector<double> &dffi = cache.dff[a][i];
-            factor1 = J * Eigen::Vector3d(dffi.data());
-            factor2 = K_conductivity * factor1;
+            Eigen::Vector3d factor1 = C * J * Eigen::Vector3d(dffi.data());
             for (size_t j = i; j < nodes.size(); ++j)
             {
                 std::vector<double> &dffj = cache.dff[a][j];
-                factor3 = J * Eigen::Vector3d(dffj.data());
-                L_e(i, j) += factor2.dot(factor3) * gauss.w[a] * detJ;
+                Eigen::Vector3d factor2 = J * Eigen::Vector3d(dffj.data());
+                L_e(i, j) += factor1.dot(factor2) * gauss.w[a] * detJ;
             }
         }
     }
@@ -264,22 +261,34 @@ void Hex8::strain_stress(Eigen::MatrixXd &Strain, Eigen::MatrixXd &Stress, Eigen
                     Stress(i, j) += H(i * 3 + j, k * 3 + l) * Strain(k, l);
 }
 
+/**
+ * @brief Compute mass matrix
+ * 
+ * M_ij(8,8) = int N_i*N_j dV
+ * @authors Romain Boman
+ */
 void Hex8::buildM(Eigen::MatrixXd &M)
 {
     CacheHex8 &cache = getCache();
     GaussHex8 &gauss = cache.gauss;
     MemHex8 &mem = getMem();
 
-    M = Eigen::MatrixXd::Zero(8, 8);
+    // Gauss integration
+    M = Eigen::Matrix<double, 8, 8>::Zero();
     for (size_t k = 0; k < gauss.p.size(); ++k)
     {
-        // calcul de la matrice jacobienne (au point de Gauss "ksi")
+        // Jacobian and shape functions
         double detJ = mem.getDetJ(k);
         std::vector<double> &ff = cache.ff[k];
-        M += Eigen::Matrix<double, 8, 1>(ff.data()) * Eigen::Matrix<double, 1, 8>(ff.data()) * gauss.w[k] * detJ; // M = M + {ff}^T [ff].wG.detJ
+
+        M += Eigen::Matrix<double, 8, 1>(ff.data()) * Eigen::Matrix<double, 1, 8>(ff.data()) * gauss.w[k] * detJ;
     }
 }
 
+/**
+ * @brief API for build methods
+ * @authors Romain Boman
+ */
 void Hex8::build(MATTYPE type, Eigen::MatrixXd &A, std::vector<double> const &u, Fct0 const &fct)
 {
     switch (type)
@@ -298,8 +307,8 @@ void Hex8::build(MATTYPE type, Eigen::MatrixXd &A, std::vector<double> const &u,
 }
 
 /**
- * @brief Compute intergal of function
- * I = int fct dV
+ * @brief Compute intergal of scalar function
+ * I = int f dV
  * @authors Adrien Crovato
  */
 double Hex8::computeV(std::vector<double> const &u, Fct0 const &fct)
@@ -308,14 +317,10 @@ double Hex8::computeV(std::vector<double> const &u, Fct0 const &fct)
     GaussHex8 &gauss = cache.gauss;
     MemHex8 &mem = getMem();
 
+    // Gauss integration
     double V = 0.0;
     for (size_t k = 0; k < gauss.p.size(); ++k)
-    {
-        // function evaluation
-        double fk = fct.eval(*this, u, k);
-        double detJ = mem.getDetJ(k);
-        V += fk * gauss.w[k] * detJ;
-    }
+        V += fct.eval(*this, u, k) * gauss.w[k] * mem.getDetJ(k);
     return V;
 }
 
@@ -325,6 +330,5 @@ double Hex8::computeV(std::vector<double> const &u, Fct0 const &fct)
  */
 double Hex8::computeV()
 {
-    MemHex8 &mem = getMem();
-    return mem.getVol();
+    return getMem().getVol();
 }
diff --git a/tbox/src/wHex8.h b/tbox/src/wHex8.h
index f3e86352..a3110597 100644
--- a/tbox/src/wHex8.h
+++ b/tbox/src/wHex8.h
@@ -39,9 +39,9 @@ class TBOX_API Hex8 : public Element
     virtual void build(MATTYPE type, Eigen::MatrixXd &A, std::vector<double> const &u, Fct0 const &fct);
     virtual void buildK(Eigen::MatrixXd &K, std::vector<double> const &u, Fct0 const &fct) override;
     virtual void buildM(Eigen::MatrixXd &M) override;
-    virtual void buildK_mechanic(Eigen::MatrixXd &K_e, Eigen::MatrixXd const &H) override;
-    virtual void buildS_thermomechanic(Eigen::MatrixXd &S_e, Eigen::MatrixXd const &D) override;
-    virtual void buildL_thermic(Eigen::MatrixXd &L_e, Eigen::MatrixXd const &K_conductivity) override;
+    virtual void buildK_mechanical(Eigen::MatrixXd &K_e, Eigen::MatrixXd const &H) override;
+    virtual void buildS_thermomechanical(Eigen::MatrixXd &S_e, Eigen::MatrixXd const &D) override;
+    virtual void buildL_thermal(Eigen::MatrixXd &L_e, Eigen::MatrixXd const &C) override;
 
     virtual void strain_stress(Eigen::MatrixXd &Strain, Eigen::MatrixXd &Stress, Eigen::MatrixXd const &H, std::vector<double> const &u) override;
 
diff --git a/tbox/src/wLine2.cpp b/tbox/src/wLine2.cpp
index 1664ef6c..989ceb08 100644
--- a/tbox/src/wLine2.cpp
+++ b/tbox/src/wLine2.cpp
@@ -38,7 +38,7 @@ Line2::~Line2()
         delete pmem;
 }
 
-/*
+/**
  * @brief Private memory handling Jacobian for Line2 Element 
  * @authors Romain Boman, Adrien Crovato
  */
@@ -51,7 +51,7 @@ MemLine2 &Line2::getMem()
     return *pmem;
 }
 
-/*
+/**
  * @brief Private cache handling shape functions and Gauss points for Line2 
  * @authors Romain Boman, Adrien Crovato
  */
@@ -65,6 +65,10 @@ Cache &Line2::getVCache()
     return getCache();
 }
 
+/**
+ * @brief Compute element unit normal vector
+ * @authors Adrien Crovato
+ */
 Pt Line2::normal()
 {
     Pt dx = (nodes[1]->pos - nodes[0]->pos).normalized();
@@ -73,6 +77,8 @@ Pt Line2::normal()
 
 /**
  * @brief Compute Jacombian determinant at Gauss point k
+ * 
+ * detJ = norm(x_i * dN_i)
  * @authors Romain Boman
  */
 double Line2::buildJ(size_t k) const
@@ -82,10 +88,7 @@ double Line2::buildJ(size_t k) const
     Eigen::Vector3d t0 = Eigen::Vector3d::Zero();
     size_t i = 0;
     for (auto it = nodes.begin(); it != nodes.end(); ++it, ++i)
-    {
-        std::vector<double> &dff = cache.dff[k][i];
-        t0 += Eigen::Vector3d((*it)->pos.x.data()) * dff[0];
-    }
+        t0 += Eigen::Vector3d((*it)->pos.x.data()) * cache.dff[k][i][0];
     return t0.norm();
 }
 
@@ -101,14 +104,10 @@ void Line2::builds(Eigen::VectorXd &s, std::vector<double> const &u, Fct0 const
     GaussLine2 &gauss = cache.gauss;
     MemLine2 &mem = getMem();
 
+    // Gauss integration
     s = Eigen::Vector2d::Zero();
     for (size_t k = 0; k < gauss.p.size(); ++k)
-    {
-        double sk = f.eval(*this, u, k);
-        double detJ = mem.getDetJ(k);
-
-        s += Eigen::Vector2d(cache.ff[k].data()) * sk * gauss.w[k] * detJ; // s = s + sk.wG.detJ
-    }
+        s += Eigen::Vector2d(cache.ff[k].data()) * f.eval(*this, u, k) * gauss.w[k] * mem.getDetJ(k);
 }
 
 /**
@@ -123,31 +122,28 @@ void Line2::builds(Eigen::VectorXd &s, std::vector<double> const &u, Fct1 const
     GaussLine2 &gauss = cache.gauss;
     MemLine2 &mem = getMem();
 
+    // Gauss integration
     s = Eigen::Vector2d::Zero();
     for (size_t k = 0; k < gauss.p.size(); ++k)
-    {
-        double sk = f.eval(*this, u, k) * normal();
-        double detJ = mem.getDetJ(k);
-
-        s += Eigen::Vector2d(cache.ff[k].data()) * sk * gauss.w[k] * detJ; // s = s + sk.wG.detJ
-    }
+        s += Eigen::Vector2d(cache.ff[k].data()) * (f.eval(*this, u, k) * normal()) * gauss.w[k] * mem.getDetJ(k);
 }
 
 /**
  * @brief Compute square of gradient along element
+ * 
+ * grad = (Delta_U / Delta_L)^2
  * @authors Adrien Crovato
  */
 double Line2::computeGrad2(std::vector<double> const &u, size_t k)
 {
-    double deltaU = u[nodes[1]->row] - u[nodes[0]->row];
-    double deltaS = computeV();
-    return deltaU / deltaS * deltaU / deltaS;
+    double dUdL = (u[nodes[1]->row] - u[nodes[0]->row]) / computeV(); // V = length of the element
+    return dUdL * dUdL;
 }
 
 /**
- * @brief Compute intergal of function
+ * @brief Compute intergal of scalar function
  * 
- * I = int fct dV
+ * I = int f dV
  * @authors Adrien Crovato
  */
 double Line2::computeV(std::vector<double> const &u, Fct0 const &fct)
@@ -156,23 +152,18 @@ double Line2::computeV(std::vector<double> const &u, Fct0 const &fct)
     GaussLine2 &gauss = cache.gauss;
     MemLine2 &mem = getMem();
 
+    // Gauss integration
     double V = 0.0;
     for (size_t k = 0; k < gauss.p.size(); ++k)
-    {
-        // evaluation de la fct a intégrer
-        double fk = fct.eval(*this, u, k);
-        double detJ = mem.getDetJ(k);
-        V += fk * gauss.w[k] * detJ;
-    }
+        V += fct.eval(*this, u, k) * gauss.w[k] * mem.getDetJ(k);
     return V;
 }
 
 /**
- * @brief Return the element volume
+ * @brief Return the element length
  * @authors Adrien Crovato
  */
 double Line2::computeV()
 {
-    MemLine2 &mem = getMem();
-    return mem.getVol();
+    return getMem().getVol();
 }
diff --git a/tbox/src/wMshDeform.cpp b/tbox/src/wMshDeform.cpp
index 2b57c30a..e0b70a36 100644
--- a/tbox/src/wMshDeform.cpp
+++ b/tbox/src/wMshDeform.cpp
@@ -287,7 +287,7 @@ void MshDeform::deform()
 
         // Elementary stiffness matrix
         Eigen::MatrixXd Ke;
-        e->buildK_linElastic(Ke, H);
+        e->buildK_mechanical(Ke, H);
 
         // Assembly
         //        tbb::spin_mutex::scoped_lock lock(mutex);
diff --git a/tbox/src/wQuad4.cpp b/tbox/src/wQuad4.cpp
index 6129e1e3..6b350c5a 100644
--- a/tbox/src/wQuad4.cpp
+++ b/tbox/src/wQuad4.cpp
@@ -37,7 +37,7 @@ Quad4::~Quad4()
         delete pmem;
 }
 
-/*
+/**
  * @brief Private memory handling Jacobian for Quad4 Element 
  * @authors Romain Boman, Adrien Crovato
  */
@@ -50,7 +50,7 @@ MemQuad4 &Quad4::getMem()
     return *pmem;
 }
 
-/*
+/**
  * @brief Private cache handling shape functions and Gauss points for Quad4 
  * @authors Romain Boman, Adrien Crovato
  */
@@ -64,6 +64,10 @@ Cache &Quad4::getVCache()
     return getCache();
 }
 
+/**
+ * @brief Compute element unit normal vector
+ * @authors Romain Boman
+ */
 Pt Quad4::normal()
 {
     Pt x1 = nodes[0]->pos;
@@ -76,6 +80,8 @@ Pt Quad4::normal()
 
 /**
  * @brief Compute Jacobian determinant at Gauss point k
+ * 
+ * detJ = norm(x_i dN_i,xi X x_i dN_i,eta)
  * @authors Romain Boman
  */
 double Quad4::buildJ(size_t k) const
@@ -94,7 +100,9 @@ double Quad4::buildJ(size_t k) const
     return t0.cross(t1).norm();
 }
 /**
- * @brief Compute Jacobian matrix at Gauss point k
+ * @brief Compute Jacobian matrix and determinant at Gauss point k
+ * 
+ * J_ij(2,2) = diN_n * xj_n (n is the node)
  * @authors Romain Boman
  */
 double Quad4::buildJ(size_t k, Eigen::MatrixXd &J) const
@@ -111,23 +119,34 @@ double Quad4::buildJ(size_t k, Eigen::MatrixXd &J) const
     return J.determinant();
 }
 
+/**
+ * @brief Compute mass matrix
+ * 
+ * S_ij(4,4) = int N_i*N_j dV (from Quad4)
+ * @authors Romain Boman
+ */
 void Quad4::buildS(Eigen::MatrixXd &S)
 {
     CacheQuad4 &cache = getCache();
     GaussQuad4 &gauss = cache.gauss;
     MemQuad4 &mem = getMem();
 
+    // Gauss integration
     S = Eigen::Matrix4d::Zero();
     for (size_t k = 0; k < gauss.p.size(); ++k)
     {
-        // Jacobian
+        // Jacobian and shape function
         double detJ = mem.getDetJ(k);
-
         std::vector<double> &ff = cache.ff[k];
-        S += Eigen::Vector4d(ff.data()) * Eigen::RowVector4d(ff.data()) * gauss.w[k] * detJ; // S = S + {ff}^T [ff].wG.detJ
+
+        S += Eigen::Vector4d(ff.data()) * Eigen::RowVector4d(ff.data()) * gauss.w[k] * detJ;
     }
 }
 
+/**
+ * @brief API for build methods
+ * @authors Romain Boman
+ */
 void Quad4::build(MATTYPE type, Eigen::MatrixXd &A)
 {
     switch (type)
@@ -143,9 +162,9 @@ void Quad4::build(MATTYPE type, Eigen::MatrixXd &A)
 }
 
 /**
- * @brief Compute intergal of function
+ * @brief Compute intergal of scalar function
  * 
- * I = int fct dV
+ * I = int f dV
  * @authors Romain Boman
  */
 double Quad4::computeV(std::vector<double> const &u, Fct0 const &fct)
@@ -154,23 +173,18 @@ double Quad4::computeV(std::vector<double> const &u, Fct0 const &fct)
     GaussQuad4 &gauss = cache.gauss;
     MemQuad4 &mem = getMem();
 
+    // Gauss integration
     double V = 0.0;
     for (size_t k = 0; k < gauss.p.size(); ++k)
-    {
-        // Function evaluation
-        double fk = fct.eval(*this, u, k);
-        double detJ = mem.getDetJ(k);
-        V += fk * gauss.w[k] * detJ;
-    }
+        V += fct.eval(*this, u, k) * gauss.w[k] * mem.getDetJ(k);
     return V;
 }
 
 /**
- * @brief Return the element volume
+ * @brief Return the element surface
  * @authors Adrien Crovato
  */
 double Quad4::computeV()
 {
-    MemQuad4 &mem = getMem();
-    return mem.getVol();
+    return getMem().getVol();
 }
\ No newline at end of file
diff --git a/tbox/src/wTetra4.cpp b/tbox/src/wTetra4.cpp
index c030915e..e2d996c1 100644
--- a/tbox/src/wTetra4.cpp
+++ b/tbox/src/wTetra4.cpp
@@ -36,7 +36,7 @@ Tetra4::~Tetra4()
         delete pmem;
 }
 
-/*
+/**
  * @brief Private memory handling Jacobian for Tetra4 Element 
  * @authors Romain Boman, Adrien Crovato
  */
@@ -49,7 +49,7 @@ MemTetra4 &Tetra4::getMem()
     return *pmem;
 }
 
-/*
+/**
  * @brief Private cache handling shape functions and Gauss points for Tetra4 
  * @authors Romain Boman, Adrien Crovato
  */
@@ -65,6 +65,8 @@ Cache &Tetra4::getVCache()
 
 /**
  * @brief Compute Jacobian Matrix at Gauss point k
+ * 
+ * J_ij(3,3) = diN_n * xj_n (n is the node)
  * @authors Romain Boman
  */
 double Tetra4::buildJ(size_t k, Eigen::MatrixXd &J) const
@@ -83,6 +85,8 @@ double Tetra4::buildJ(size_t k, Eigen::MatrixXd &J) const
 
 /**
  * @brief Compute mass matrix
+ * 
+ * M_ij(4,4) = int N_i*N_j dV
  * @authors Romain Boman
  */
 void Tetra4::buildM(Eigen::MatrixXd &M)
@@ -91,21 +95,22 @@ void Tetra4::buildM(Eigen::MatrixXd &M)
     GaussTetra4 &gauss = cache.gauss;
     MemTetra4 &mem = getMem();
 
+    // Gauss integration
     M = Eigen::Matrix4d::Zero();
     for (size_t k = 0; k < gauss.p.size(); ++k)
     {
-        // Jacobian
+        // Jacobian and shape functions
         double detJ = mem.getDetJ(k);
-
         std::vector<double> &ff = cache.ff[k];
-        M += Eigen::Vector4d(ff.data()) * Eigen::RowVector4d(ff.data()) * gauss.w[k] * detJ; // M = M + {ff}^T [ff].wG.detJ
+
+        M += Eigen::Vector4d(ff.data()) * Eigen::RowVector4d(ff.data()) * gauss.w[k] * detJ;
     }
 }
 
 /**
  * @brief Compute stiffness matrix for scalar field
  * 
- * K_ij(4,4) = int fct*dN_j*dN_i dV
+ * K_ij(4,4) = int f*dN_j*dN_i dV
  * @authors Romain Boman, Adrien Crovato
  */
 void Tetra4::buildK(Eigen::MatrixXd &K, std::vector<double> const &u, Fct0 const &fct)
@@ -114,29 +119,18 @@ void Tetra4::buildK(Eigen::MatrixXd &K, std::vector<double> const &u, Fct0 const
     GaussTetra4 &gauss = cache.gauss;
     MemTetra4 &mem = getMem();
 
+    // Gauss integration
     K = Eigen::Matrix4d::Zero();
-    Eigen::Vector3d factor1;
-    Eigen::Vector3d factor2;
     for (size_t k = 0; k < gauss.p.size(); ++k)
     {
-        // Function and Jacobian evaluation
-        double fk = fct.eval(*this, u, k);
-        double detJ = mem.getDetJ(k);
+        // Jacobian inverse and shape functions
         Eigen::Matrix3d const &J = mem.getJinv(k);
-
-        // compute stiffness matrix for each GP
+        Eigen::Matrix<double, 3, 4> dN;
         for (size_t i = 0; i < nodes.size(); ++i)
-        {
-            std::vector<double> &dffi = cache.dff[k][i];
-            factor1 = J * Eigen::Vector3d(dffi.data());
+            dN.col(i) = Eigen::Vector3d(cache.dff[k][i].data());
 
-            for (size_t j = 0; j < nodes.size(); ++j)
-            {
-                std::vector<double> &dffj = cache.dff[k][j];
-                factor2 = J * Eigen::Vector3d(dffj.data());
-                K(i, j) += factor1.dot(factor2) * gauss.w[k] * detJ * fk;
-            }
-        }
+        // Elementary stiffness matrix
+        K += (J * dN).transpose() * J * dN * fct.eval(*this, u, k) * gauss.w[k] * mem.getDetJ(k);
     }
 }
 
@@ -152,30 +146,20 @@ void Tetra4::buildDK(Eigen::MatrixXd &K, std::vector<double> const &u, Fct0 cons
     GaussTetra4 &gauss = cache.gauss;
     MemTetra4 &mem = getMem();
 
+    // Gauss integration
     K = Eigen::Matrix4d::Zero();
-    Eigen::Vector3d factor1;
-    Eigen::Vector3d factor2;
     for (size_t k = 0; k < gauss.p.size(); ++k)
     {
-        // "derivative" of function, Jacobian and gradient evaluation
-        double dfk = fct.evalD(*this, u, k);
-        double detJ = mem.getDetJ(k);
+        // Jacobian inverse, shape functions and gradient
         Eigen::Matrix3d const &J = mem.getJinv(k);
+        Eigen::Matrix<double, 3, 4> dN;
+        for (size_t i = 0; i < nodes.size(); ++i)
+            dN.col(i) = Eigen::Vector3d(cache.dff[k][i].data());
         Eigen::VectorXd gradu;
-        computeGrad(u, gradu, k);
+        this->computeGrad(u, gradu, k);
 
-        // computation of K
-        for (size_t i = 0; i < nodes.size(); ++i)
-        {
-            std::vector<double> &dffi = cache.dff[k][i];
-            factor1 = J * Eigen::Vector3d(dffi.data());
-            for (size_t j = 0; j < nodes.size(); ++j)
-            {
-                std::vector<double> &dffj = cache.dff[k][j];
-                factor2 = J * Eigen::Vector3d(dffj.data());
-                K(i, j) += gradu.dot(factor1) * gradu.dot(factor2) * gauss.w[k] * detJ * dfk;
-            }
-        }
+        // Elementary stiffness matrix
+        K += (gradu.transpose() * J * dN).transpose() * gradu.transpose() * J * dN * fct.evalD(*this, u, k) * gauss.w[k] * mem.getDetJ(k);
     }
 }
 
@@ -191,181 +175,121 @@ void Tetra4::buildDs(Eigen::VectorXd &s, std::vector<double> const &u, Fct0 cons
     GaussTetra4 &gauss = cache.gauss;
     MemTetra4 &mem = getMem();
 
+    // Gauss integration
     s = Eigen::Vector4d::Zero();
-    Eigen::Vector3d factor1;
     for (size_t k = 0; k < gauss.p.size(); ++k)
     {
-        // Gradient, function and Jacobian
+        // Shape functions and gradient
+        Eigen::Matrix<double, 3, 4> dN;
+        for (size_t i = 0; i < nodes.size(); ++i)
+            dN.col(i) = Eigen::Vector3d(cache.dff[k][i].data());
         Eigen::VectorXd gradu;
         this->computeGrad(u, gradu, k);
-        double fk = f.eval(*this, u, k);
-        double detJ = mem.getDetJ(k);
-        Eigen::Matrix3d const &J = mem.getJinv(k);
 
-        // s(i) = f * gradu * gradN(i)
-        for (size_t i = 0; i < nodes.size(); ++i)
-        {
-            std::vector<double> &dffi = cache.dff[k][i];
-            factor1 = J * Eigen::Vector3d(dffi.data());
-            s(i) += gradu.dot(factor1) * gauss.w[k] * detJ * fk;
-        }
+        // Elementary flux vector
+        s += gradu.transpose() * mem.getJinv(k) * dN * f.eval(*this, u, k) * gauss.w[k] * mem.getDetJ(k);
     }
 }
 
 /**
  * @brief Compute linear elasticity stiffness matrix
+ * 
+ * K_ij(12,12) = int eps_k H_ijkl eps_l dV = B(12,6)H(6,6)B(6,12)
  * @authors Adrien Crovato
- * @todo this is a clean duplicate of buildK_mechnical, should be merged
  */
-void Tetra4::buildK_linElastic(Eigen::MatrixXd &K, Eigen::MatrixXd const &H)
+void Tetra4::buildK_mechanical(Eigen::MatrixXd &K, Eigen::MatrixXd const &H)
 {
     CacheTetra4 &cache = getCache();
     GaussTetra4 &gauss = cache.gauss;
     MemTetra4 &mem = getMem();
 
     K = Eigen::MatrixXd::Zero(12, 12);
-    Eigen::Vector3d factori;
     for (size_t k = 0; k < gauss.p.size(); ++k)
     {
-        // Jacobian
-        double detJ = mem.getDetJ(k);
+        // Jacobian inverse
         Eigen::Matrix3d const &invJ = mem.getJinv(k);
-
-        // Fill B matrix
+        // Fill B matrix (shape functions)
         Eigen::MatrixXd B = Eigen::MatrixXd::Zero(6, 3 * nodes.size());
         for (size_t i = 0; i < nodes.size(); ++i)
         {
             // Compute [Ni,x Ni,y, Ni_z]
             std::vector<double> &dffi = cache.dff[k][i];
-            factori = invJ * Eigen::Vector3d(dffi.data());
-            B(0, 3 * i) = factori(0);
-            B(1, 3 * i + 1) = factori(1);
-            B(2, 3 * i + 2) = factori(2);
-            B(3, 3 * i + 1) = factori(2);
-            B(3, 3 * i + 2) = factori(1);
-            B(4, 3 * i) = factori(2);
-            B(4, 3 * i + 2) = factori(0);
-            B(5, 3 * i) = factori(1);
-            B(5, 3 * i + 1) = factori(0);
+            Eigen::Vector3d dN = invJ * Eigen::Vector3d(dffi.data());
+            B(0, 3 * i) = dN(0);
+            B(1, 3 * i + 1) = dN(1);
+            B(2, 3 * i + 2) = dN(2);
+            B(3, 3 * i + 1) = dN(2);
+            B(3, 3 * i + 2) = dN(1);
+            B(4, 3 * i) = dN(2);
+            B(4, 3 * i + 2) = dN(0);
+            B(5, 3 * i) = dN(1);
+            B(5, 3 * i + 1) = dN(0);
         }
 
         // Compute stiffness matrix
-        K += B.transpose() * H * B * detJ * gauss.w[k];
+        K += B.transpose() * H * B * gauss.w[k] * mem.getDetJ(k);
     }
 }
 
 /* -------------------------------------------------------------------------- */
-/**
- * @brief Compute mechanical stiffness matrix
- * @authors Kim Liegeois
- */
-void Tetra4::buildK_mechanic(Eigen::MatrixXd &K_e, Eigen::MatrixXd const &H)
-{
-    CacheTetra4 &cache = getCache();
-    GaussTetra4 &gauss = cache.gauss;
-    MemTetra4 &mem = getMem();
-
-    K_e = Eigen::MatrixXd::Zero(12, 12);
-    Eigen::Vector3d factor1;
-    Eigen::Vector3d factor2;
-    Eigen::Vector3d factor3;
-    Eigen::Matrix3d TMP1;
-    for (size_t a = 0; a < gauss.p.size(); ++a)
-    {
-        // calcul de la matrice jacobienne (au point de Gauss "ksi")
-        double detJ = mem.getDetJ(a);
-        Eigen::Matrix3d const &J = mem.getJinv(a);
-
-        // calcul de K (au point de Gauss "ksi")
-        for (size_t i = 0; i < nodes.size(); ++i)
-        {
-            std::vector<double> &dffi = cache.dff[a][i];
-            factor1 = J * Eigen::Vector3d(dffi.data());
-            for (size_t j = i; j < nodes.size(); ++j)
-            {
-                std::vector<double> &dffj = cache.dff[a][j];
-                factor2 = J * Eigen::Vector3d(dffj.data());
-                for (size_t k = 0; k < 3; ++k)
-                    for (size_t m = 0; m < 3; ++m)
-                    {
-                        for (size_t l = 0; l < 3; ++l)
-                            for (size_t n = 0; n < 3; ++n)
-                                TMP1(l, n) = H(k * 3 + l, m * 3 + n);
-                        factor3 = TMP1 * factor2;
-                        K_e(i * 3 + k, j * 3 + m) += factor1.dot(factor3) * gauss.w[a] * detJ;
-                    }
-            }
-        }
-    }
-    for (size_t i = 0; i < 3 * nodes.size(); ++i)
-        for (size_t j = i; j < 3 * nodes.size(); ++j)
-            K_e(j, i) = K_e(i, j);
-}
 
 /**
  * @brief Compute thermomechanical mass matrix
  * @authors Kim Liegeois
  */
-void Tetra4::buildS_thermomechanic(Eigen::MatrixXd &S_e, Eigen::MatrixXd const &D)
+void Tetra4::buildS_thermomechanical(Eigen::MatrixXd &S_e, Eigen::MatrixXd const &D)
 {
     CacheTetra4 &cache = getCache();
     GaussTetra4 &gauss = cache.gauss;
     MemTetra4 &mem = getMem();
 
+    // Gauss integration
     S_e = Eigen::MatrixXd::Zero(12, 4);
-    Eigen::Vector3d factor1;
-    Eigen::Vector3d factor2;
     for (size_t a = 0; a < gauss.p.size(); ++a)
     {
-        // calcul de la matrice jacobienne (au point de Gauss "ksi")
+        // Jacobian and shape functions
         double detJ = mem.getDetJ(a);
         Eigen::Matrix3d const &J = mem.getJinv(a);
         std::vector<double> &ff = cache.ff[a];
 
-        // calcul de K (au point de Gauss "ksi")
         for (size_t i = 0; i < nodes.size(); ++i)
         {
             std::vector<double> &dffi = cache.dff[a][i];
-            factor1 = J * Eigen::Vector3d(dffi.data());
-            factor2 = D * factor1;
+            Eigen::Vector3d factor = D * J * Eigen::Vector3d(dffi.data());
             for (size_t j = 0; j < nodes.size(); ++j)
                 for (size_t k = 0; k < 3; ++k)
-                    S_e(i * 3 + k, j) += factor2[k] * ff[j] * gauss.w[a] * detJ;
+                    S_e(i * 3 + k, j) += factor(k) * ff[j] * gauss.w[a] * detJ;
         }
     }
 }
 
 /**
- * @brief Compute thermic matrix
+ * @brief Compute thermal matrix
  * @authors Kim Liegeois
  */
-void Tetra4::buildL_thermic(Eigen::MatrixXd &L_e, Eigen::MatrixXd const &K_conductivity)
+void Tetra4::buildL_thermal(Eigen::MatrixXd &L_e, Eigen::MatrixXd const &C)
 {
     CacheTetra4 &cache = getCache();
     GaussTetra4 &gauss = cache.gauss;
     MemTetra4 &mem = getMem();
 
+    // Gauss integration
     L_e = Eigen::Matrix4d::Zero();
-    Eigen::Vector3d factor1;
-    Eigen::Vector3d factor2;
-    Eigen::Vector3d factor3;
     for (size_t a = 0; a < gauss.p.size(); ++a)
     {
-        // calcul de la matrice jacobienne (au point de Gauss "ksi")
+        // Jacobian
         double detJ = mem.getDetJ(a);
         Eigen::Matrix3d const &J = mem.getJinv(a);
 
-        // calcul de K (au point de Gauss "ksi")
         for (size_t i = 0; i < nodes.size(); ++i)
         {
             std::vector<double> &dffi = cache.dff[a][i];
-            factor1 = J * Eigen::Vector3d(dffi.data());
-            factor2 = K_conductivity * factor1;
+            Eigen::Vector3d factor1 = C * J * Eigen::Vector3d(dffi.data());
             for (size_t j = i; j < nodes.size(); ++j)
             {
                 std::vector<double> &dffj = cache.dff[a][j];
-                factor3 = J * Eigen::Vector3d(dffj.data());
-                L_e(i, j) += factor2.dot(factor3) * gauss.w[a] * detJ;
+                Eigen::Vector3d factor2 = J * Eigen::Vector3d(dffj.data());
+                L_e(i, j) += factor1.dot(factor2) * gauss.w[a] * detJ;
             }
         }
     }
@@ -434,7 +358,7 @@ void Tetra4::computeGrad(std::vector<double> const &u, Eigen::VectorXd &grad, si
     CacheTetra4 &cache = getCache();
     MemTetra4 &mem = getMem();
 
-    // local matrix of sf derivatives, solution vector and Jacobian
+    // local matrix of sf derivatives and solution vector
     Eigen::MatrixXd gradN(3, nodes.size());
     Eigen::Vector4d ue;
     for (size_t i = 0; i < nodes.size(); ++i)
@@ -442,9 +366,8 @@ void Tetra4::computeGrad(std::vector<double> const &u, Eigen::VectorXd &grad, si
         gradN.col(i) = Eigen::Vector3d(cache.dff[k][i].data());
         ue(i) = u[nodes[i]->row];
     }
-    Eigen::Matrix3d const &Jinv = mem.getJinv(k);
     // gradient in global axis: inv(J)_ij * d_jN_i * ue_i
-    grad = Jinv * gradN * ue;
+    grad = mem.getJinv(k) * gradN * ue;
 }
 
 /**
@@ -459,9 +382,9 @@ double Tetra4::computeGrad2(std::vector<double> const &u, size_t k)
 }
 
 /**
- * @brief Compute intergal of function
+ * @brief Compute intergal of scalar function
  * 
- * I = int fct dV
+ * I = int f dV
  * @authors Adrien Crovato
  */
 double Tetra4::computeV(std::vector<double> const &u, Fct0 const &fct)
@@ -470,14 +393,10 @@ double Tetra4::computeV(std::vector<double> const &u, Fct0 const &fct)
     GaussTetra4 &gauss = cache.gauss;
     MemTetra4 &mem = getMem();
 
+    // Gauss integration
     double V = 0.0;
     for (size_t k = 0; k < gauss.p.size(); ++k)
-    {
-        // function evaluation
-        double fk = fct.eval(*this, u, k);
-        double detJ = mem.getDetJ(k);
-        V += fk * gauss.w[k] * detJ;
-    }
+        V += fct.eval(*this, u, k) * gauss.w[k] * mem.getDetJ(k);
     return V;
 }
 
@@ -487,6 +406,5 @@ double Tetra4::computeV(std::vector<double> const &u, Fct0 const &fct)
  */
 double Tetra4::computeV()
 {
-    MemTetra4 &mem = getMem();
-    return mem.getVol();
+    return getMem().getVol();
 }
diff --git a/tbox/src/wTetra4.h b/tbox/src/wTetra4.h
index 17a10f90..3795dad6 100644
--- a/tbox/src/wTetra4.h
+++ b/tbox/src/wTetra4.h
@@ -40,12 +40,11 @@ class TBOX_API Tetra4 : public Element
     virtual void buildK(Eigen::MatrixXd &K, std::vector<double> const &u, Fct0 const &fct) override;
     virtual void buildDK(Eigen::MatrixXd &K, std::vector<double> const &u, Fct0 const &fct) override;
     virtual void buildDs(Eigen::VectorXd &s, std::vector<double> const &u, Fct0 const &f) override;
-    virtual void buildK_linElastic(Eigen::MatrixXd &K, Eigen::MatrixXd const &H) override;
+    virtual void buildK_mechanical(Eigen::MatrixXd &K, Eigen::MatrixXd const &H) override;
 
     /* @todo Kim's work, will have to be cleaned at some point */
-    virtual void buildK_mechanic(Eigen::MatrixXd &K_e, Eigen::MatrixXd const &H) override;
-    virtual void buildS_thermomechanic(Eigen::MatrixXd &S_e, Eigen::MatrixXd const &D) override;
-    virtual void buildL_thermic(Eigen::MatrixXd &L_e, Eigen::MatrixXd const &K_conductivity) override;
+    virtual void buildS_thermomechanical(Eigen::MatrixXd &S_e, Eigen::MatrixXd const &D) override;
+    virtual void buildL_thermal(Eigen::MatrixXd &L_e, Eigen::MatrixXd const &C) override;
     virtual void strain_stress(Eigen::MatrixXd &Strain, Eigen::MatrixXd &Stress, Eigen::MatrixXd const &H, std::vector<double> const &u) override;
     /* --- */
 
diff --git a/tbox/src/wTri3.cpp b/tbox/src/wTri3.cpp
index 961e2aa3..ee4391c2 100644
--- a/tbox/src/wTri3.cpp
+++ b/tbox/src/wTri3.cpp
@@ -39,7 +39,7 @@ Tri3::~Tri3()
         delete pmem;
 }
 
-/*
+/**
  * @brief Private memory handling Jacobian for Tri3 Element 
  * @authors Romain Boman, Adrien Crovato
  */
@@ -52,7 +52,7 @@ MemTri3 &Tri3::getMem()
     return *pmem;
 }
 
-/*
+/**
  * @brief Private cache handling shape functions and Gauss points for Tri3 
  * @authors Romain Boman, Adrien Crovato
  */
@@ -66,6 +66,10 @@ Cache &Tri3::getVCache()
     return getCache();
 }
 
+/**
+ * @brief Compute element unit normal vector
+ * @authors Adrien Crovato
+ */
 Pt Tri3::normal()
 {
     Pt x1 = nodes[0]->pos;
@@ -77,7 +81,9 @@ Pt Tri3::normal()
 
 /**
  * @brief Compute Jacobian determinant at Gauss point k
- * @authors Romain Boman
+ * 
+ * detJ = norm(x_i dN_i,xi X x_i dN_i,eta)
+ * @authors Romain Boman, Adrien Crovato
  */
 double Tri3::buildJ(size_t k) const
 {
@@ -95,8 +101,10 @@ double Tri3::buildJ(size_t k) const
     return t0.cross(t1).norm();
 }
 /**
- * @brief Compute Jacobian matrix at Gauss point k
- * @authors Romain Boman
+ * @brief Compute Jacobian matrix and determinant at Gauss point k
+ * 
+ * J_ij(2,2) = diN_n * xj_n (n is the node)
+ * @authors Romain Boman, Adrien Crovato
  */
 double Tri3::buildJ(size_t k, Eigen::MatrixXd &J) const
 {
@@ -115,8 +123,8 @@ double Tri3::buildJ(size_t k, Eigen::MatrixXd &J) const
 /**
  * @brief Compute stiffness matrix for scalar field
  * 
- * K_ij(3,3) = int fct*dN_j*dN_i dV
- * @authors Romain Boman
+ * K_ij(3,3) = int f*dN_j*dN_i dV
+ * @authors Romain Boman, Adrien Crovato
  */
 void Tri3::buildK(Eigen::MatrixXd &K, std::vector<double> const &u, Fct0 const &fct)
 {
@@ -124,38 +132,27 @@ void Tri3::buildK(Eigen::MatrixXd &K, std::vector<double> const &u, Fct0 const &
     GaussTri3 &gauss = cache.gauss;
     MemTri3 &mem = getMem();
 
+    // Gauss integration
     K = Eigen::Matrix3d::Zero();
-    Eigen::Vector2d factor1;
-    Eigen::Vector2d factor2;
     for (size_t k = 0; k < gauss.p.size(); ++k)
     {
-        // Function and Jacobian inverse
-        double fk = fct.eval(*this, u, k);
-        double detJ = mem.getDetJ(k);
+        // Jacobian inverse and shape functions
         Eigen::Matrix2d const &J = mem.getJinv(k);
-
-        // Elementary stiffness matrix
+        Eigen::Matrix<double, 2, 3> dN;
         for (size_t i = 0; i < nodes.size(); ++i)
-        {
-            std::vector<double> &dffi = cache.dff[k][i];
-            factor1 = J * Eigen::Vector2d(dffi.data());
-
-            for (size_t j = 0; j < nodes.size(); ++j)
-            {
-                std::vector<double> &dffj = cache.dff[k][j];
-                factor2 = J * Eigen::Vector2d(dffj.data());
+            dN.col(i) = Eigen::Vector2d(cache.dff[k][i].data());
 
-                K(i, j) += factor1.dot(factor2) * gauss.w[k] * detJ * fk;
-            }
-        }
-        // other way, for the future
-        //Eigen::Matrix<double, 2, 3> dN;
-        //for (size_t i = 0; i < nodes.size(); ++i)
-        //    dN.col(i) = Eigen::Vector2d(cache.dff[k][i].data());
-        //K = (J * dN).transpose() * J * dN * gauss.w[k] * detJ * fk;
+        // Elementary stiffness matrix
+        K += (J * dN).transpose() * J * dN * fct.eval(*this, u, k) * gauss.w[k] * mem.getDetJ(k);
     }
 }
 
+/**
+ * @brief Compute stiffness matrix for scalar field
+ * 
+ * K_ij(3,3) = int [f]*dN_j*dN_i dV
+ * @authors Romain Boman
+ */
 void Tri3::buildK(Eigen::MatrixXd &K, std::vector<double> const &u, Fct2 const &fct, bool fake)
 {
     CacheTri3 &cache = getCache();
@@ -171,33 +168,21 @@ void Tri3::buildK(Eigen::MatrixXd &K, std::vector<double> const &u, Fct2 const &
     }
     else // true run - use MPI cached results
     {
+        // Gauss integration
         MemTri3 &mem = getMem();
         K = Eigen::Matrix3d::Zero();
-        Eigen::Vector2d factor0;
-        Eigen::Vector2d factor1;
-        Eigen::Vector2d factor2;
         for (size_t k = 0; k < gauss.p.size(); ++k)
         {
-            // Function and Jacobian inverse
+            // Jacobian inverse, shape functions and function evaluation
+            Eigen::Matrix2d const &J = mem.getJinv(k);
+            Eigen::Matrix<double, 2, 3> dN;
+            for (size_t i = 0; i < nodes.size(); ++i)
+                dN.col(i) = Eigen::Vector2d(cache.dff[k][i].data());
             Eigen::MatrixXd fk;
             fct.eval(*this, u, k, fk, fake);
-            double detJ = mem.getDetJ(k);
-            Eigen::Matrix2d const &J = mem.getJinv(k);
 
             // Elementary stiffness matrix
-            for (size_t i = 0; i < nodes.size(); ++i)
-            {
-                std::vector<double> &dffi = cache.dff[k][i];
-                factor0 = J * Eigen::Vector2d(dffi.data());
-                factor1 = fk * factor0;
-
-                for (size_t j = 0; j < nodes.size(); ++j)
-                {
-                    std::vector<double> &dffj = cache.dff[k][j];
-                    factor2 = J * Eigen::Vector2d(dffj.data());
-                    K(i, j) += factor1.dot(factor2) * gauss.w[k] * detJ;
-                }
-            }
+            K += (fk * J * dN).transpose() * J * dN * gauss.w[k] * mem.getDetJ(k);
         }
     }
 }
@@ -208,35 +193,33 @@ void Tri3::buildK(Eigen::MatrixXd &K, std::vector<double> const &u, Fct2 const &
  * K_ij(6,6) = int eps_k H_ijkl eps_l dV = B(6,3)H(3,3)B(3,6)
  * @authors Adrien Crovato
  */
-void Tri3::buildK_linElastic(Eigen::MatrixXd &K, Eigen::MatrixXd const &H)
+void Tri3::buildK_mechanical(Eigen::MatrixXd &K, Eigen::MatrixXd const &H)
 {
     CacheTri3 &cache = getCache();
     GaussTri3 &gauss = cache.gauss;
     MemTri3 &mem = getMem();
 
+    // Gauss integration
     K = Eigen::MatrixXd::Zero(6, 6);
-    Eigen::Vector2d factori;
     for (size_t k = 0; k < gauss.p.size(); ++k)
     {
         // Jacobian inverse
-        double detJ = mem.getDetJ(k);
         Eigen::Matrix2d const &invJ = mem.getJinv(k);
-
-        // Fill B matrix
+        // Fill B matrix (shape functions)
         Eigen::MatrixXd B = Eigen::MatrixXd::Zero(3, 6);
         for (size_t i = 0; i < nodes.size(); ++i)
         {
             // Compute [Ni,x Ni,y]
             std::vector<double> &dffi = cache.dff[k][i];
-            factori = invJ * Eigen::Vector2d(dffi.data());
-            B(0, 2 * i) = factori(0);
-            B(1, 2 * i + 1) = factori(1);
-            B(2, 2 * i + 1) = factori(0);
-            B(2, 2 * i) = factori(1);
+            Eigen::Vector2d dN = invJ * Eigen::Vector2d(dffi.data());
+            B(0, 2 * i) = dN(0);
+            B(1, 2 * i + 1) = dN(1);
+            B(2, 2 * i + 1) = dN(0);
+            B(2, 2 * i) = dN(1);
         }
 
         // Compute stiffness matrix
-        K += B.transpose() * H * B * detJ * gauss.w[k];
+        K += B.transpose() * H * B * gauss.w[k] * mem.getDetJ(k);
     }
 }
 
@@ -252,30 +235,20 @@ void Tri3::buildDK(Eigen::MatrixXd &K, std::vector<double> const &u, Fct0 const
     GaussTri3 &gauss = cache.gauss;
     MemTri3 &mem = getMem();
 
+    // Gauss integration
     K = Eigen::Matrix3d::Zero();
-    Eigen::Vector2d factor1;
-    Eigen::Vector2d factor2;
     for (size_t k = 0; k < gauss.p.size(); ++k)
     {
-        // "derivative" of f, gradient and inverse Jacobian
-        double dfk = fct.evalD(*this, u, k);
+        // Jacobian inverse, shape functions and gradient
+        Eigen::Matrix2d const &J = mem.getJinv(k);
+        Eigen::Matrix<double, 2, 3> dN;
+        for (size_t i = 0; i < nodes.size(); ++i)
+            dN.col(i) = Eigen::Vector2d(cache.dff[k][i].data());
         Eigen::VectorXd gradu;
         this->computeGrad(u, gradu, k);
-        double detJ = mem.getDetJ(k);
-        Eigen::Matrix2d const &J = mem.getJinv(k);
 
-        // computation of K
-        for (size_t i = 0; i < nodes.size(); ++i)
-        {
-            std::vector<double> &dffi = cache.dff[k][i];
-            factor1 = J * Eigen::Vector2d(dffi.data());
-            for (size_t j = 0; j < nodes.size(); ++j)
-            {
-                std::vector<double> &dffj = cache.dff[k][j];
-                factor2 = J * Eigen::Vector2d(dffj.data());
-                K(i, j) += gradu.dot(factor1) * gradu.dot(factor2) * gauss.w[k] * detJ * dfk;
-            }
-        }
+        // Elementary stiffness matrix
+        K += (gradu.transpose() * J * dN).transpose() * gradu.transpose() * J * dN * fct.evalD(*this, u, k) * gauss.w[k] * mem.getDetJ(k);
     }
 }
 
@@ -291,13 +264,10 @@ void Tri3::builds(Eigen::VectorXd &s, std::vector<double> const &u, Fct0 const &
     GaussTri3 &gauss = cache.gauss;
     MemTri3 &mem = getMem();
 
+    // Gauss integration
     s = Eigen::Vector3d::Zero();
     for (size_t k = 0; k < gauss.p.size(); ++k)
-    {
-        double sk = f.eval(*this, u, k);
-        double detJ = mem.getDetJ(k);
-        s += Eigen::Vector3d(cache.ff[k].data()) * sk * gauss.w[k] * detJ; // s = s + sk.wG.detJ
-    }
+        s += Eigen::Vector3d(cache.ff[k].data()) * f.eval(*this, u, k) * gauss.w[k] * mem.getDetJ(k);
 }
 
 /**
@@ -312,13 +282,11 @@ void Tri3::builds(Eigen::VectorXd &s, std::vector<double> const &u, Fct1 const &
     GaussTri3 &gauss = cache.gauss;
     MemTri3 &mem = getMem();
 
+    // Gauss integration
     s = Eigen::Vector3d::Zero();
     for (size_t k = 0; k < gauss.p.size(); ++k)
-    {
-        double sk = f.eval(*this, u, k) * normal();
-        double detJ = mem.getDetJ(k);
-        s += Eigen::Vector3d(cache.ff[k].data()) * sk * gauss.w[k] * detJ; // s = s + sk.wG.detJ
-    }
+        s += Eigen::Vector3d(cache.ff[k].data()) * (f.eval(*this, u, k) * normal()) * gauss.w[k] * mem.getDetJ(k);
+
 }
 
 /**
@@ -333,30 +301,26 @@ void Tri3::buildDs(Eigen::VectorXd &s, std::vector<double> const &u, Fct0 const
     GaussTri3 &gauss = cache.gauss;
     MemTri3 &mem = getMem();
 
+    // Gauss integration
     s = Eigen::Vector3d::Zero();
-    Eigen::Vector2d factor1;
     for (size_t k = 0; k < gauss.p.size(); ++k)
     {
+        // Shape functions and gradient
+        Eigen::Matrix<double, 2, 3> dN;
+        for (size_t i = 0; i < nodes.size(); ++i)
+            dN.col(i) = Eigen::Vector2d(cache.dff[k][i].data());
         Eigen::VectorXd gradu;
         this->computeGrad(u, gradu, k);
-        double fk = f.eval(*this, u, k);
-        double detJ = mem.getDetJ(k);
-        Eigen::Matrix2d const &J = mem.getJinv(k);
 
-        // s(i) = f * gradu * gradN(i)
-        for (size_t i = 0; i < nodes.size(); ++i)
-        {
-            std::vector<double> &dffi = cache.dff[k][i];
-            factor1 = J * Eigen::Vector2d(dffi.data());
-            s(i) += gradu.dot(factor1) * gauss.w[k] * detJ * fk;
-        }
+        // Elementary flux vector
+        s += gradu.transpose() * mem.getJinv(k) * dN * f.eval(*this, u, k) * gauss.w[k] * mem.getDetJ(k);
     }
 }
 
 /**
- * @brief Compute something
+ * @brief Compute mass matrix
  * 
- * S_ij(3,3) = int N_i*N_j dV (from Quad4)
+ * S_ij(3,3) = int N_i*N_j dV
  * @authors Romain Boman
  */
 void Tri3::buildS(Eigen::MatrixXd &S)
@@ -365,6 +329,7 @@ void Tri3::buildS(Eigen::MatrixXd &S)
     GaussTri3 &gauss = cache.gauss;
     MemTri3 &mem = getMem();
 
+    // Gauss integration
     S = Eigen::Matrix3d::Zero();
     for (size_t k = 0; k < gauss.p.size(); ++k)
     {
@@ -372,10 +337,14 @@ void Tri3::buildS(Eigen::MatrixXd &S)
         double detJ = mem.getDetJ(k);
         std::vector<double> &ff = cache.ff[k];
 
-        S += Eigen::Vector3d(ff.data()) * Eigen::RowVector3d(ff.data()) * gauss.w[k] * detJ; // S = S + {ff}^T [ff] * wG * detJ
+        S += Eigen::Vector3d(ff.data()) * Eigen::RowVector3d(ff.data()) * gauss.w[k] * detJ;
     }
 }
 
+/**
+ * @brief API for build methods
+ * @authors Romain Boman
+ */
 void Tri3::build(MATTYPE type, Eigen::MatrixXd &A, std::vector<double> const &u, Fct0 const &fct)
 {
     switch (type)
@@ -402,7 +371,7 @@ void Tri3::computeGrad(std::vector<double> const &u, Eigen::VectorXd &grad, size
     CacheTri3 &cache = getCache();
     MemTri3 &mem = getMem();
 
-    // local matrix of sf derivatives, solution vector and Jacobian
+    // local matrix of sf derivatives and solution vector
     Eigen::MatrixXd gradN(2, nodes.size());
     Eigen::Vector3d ue;
     for (size_t i = 0; i < nodes.size(); ++i)
@@ -410,9 +379,8 @@ void Tri3::computeGrad(std::vector<double> const &u, Eigen::VectorXd &grad, size
         gradN.col(i) = Eigen::Vector2d(cache.dff[k][i].data());
         ue(i) = u[nodes[i]->row];
     }
-    Eigen::Matrix2d const &Jinv = mem.getJinv(k);
     // Gradient in global axis: inv(J)_ij * d_jN_i * ue_i
-    grad = Jinv * gradN * ue;
+    grad = mem.getJinv(k) * gradN * ue;
 }
 
 /**
@@ -427,7 +395,10 @@ double Tri3::computeGrad2(std::vector<double> const &u, size_t k)
 }
 
 /**
- *  calculation of int_V -gradu.fct dV
+ * @brief Compute flux
+ * 
+ * qV_i(2) = int -gradu * f dV
+ * @authors Romain Boman
  */
 void Tri3::computeqV(std::vector<double> const &u, Eigen::VectorXd &qV, Fct0 const &fct)
 {
@@ -435,21 +406,24 @@ void Tri3::computeqV(std::vector<double> const &u, Eigen::VectorXd &qV, Fct0 con
     GaussTri3 &gauss = cache.gauss;
     MemTri3 &mem = getMem();
 
+    // Gauss integration
     qV = Eigen::Vector2d::Zero();
     for (size_t k = 0; k < gauss.p.size(); ++k)
     {
-        // Gradient function and Jacobian evaluation
+        // Gradient
         Eigen::VectorXd gradk;
         computeGrad(u, gradk, k);
-        double fk = fct.eval(*this, u, k);
-        double detJ = mem.getDetJ(k);
 
-        qV -= gradk * fk * gauss.w[k] * detJ; // qV = qV + fk.wG.detJ
+        // Elementary flux
+        qV -= gradk * fct.eval(*this, u, k) * gauss.w[k] * mem.getDetJ(k);
     }
 }
 
 /**
- *  calculation of int_V flux grad N_j dV
+ * @brief Compute flux
+ * 
+ * qV_i(3) = int [f] gradu N_i dV
+ * @authors Romain Boman
  */
 void Tri3::computeqint(std::vector<double> const &u, Eigen::VectorXd &qV, Fct2 const &fct)
 {
@@ -457,32 +431,29 @@ void Tri3::computeqint(std::vector<double> const &u, Eigen::VectorXd &qV, Fct2 c
     GaussTri3 &gauss = cache.gauss;
     MemTri3 &mem = getMem();
 
+    // Gauss integration
     qV = Eigen::Vector3d::Zero();
     for (size_t k = 0; k < gauss.p.size(); ++k)
     {
-        // Gradient and flux evaluation
+        // Shape functions, gradient and flux evaluation
+        Eigen::Matrix<double, 2, 3> dN;
+        for (size_t i = 0; i < nodes.size(); ++i)
+            dN.col(i) = Eigen::Vector2d(cache.dff[k][i].data());
         Eigen::VectorXd gradk;
         computeGrad(u, gradk, k);
         Eigen::MatrixXd fk(2, 2);
         fct.eval(*this, u, k, fk, false);
-        double detJ = mem.getDetJ(k);
-        Eigen::Vector2d flux;
-        flux = fk * gradk;
 
-        // calcul du gradient des fcts de forme et produit scalaire
-        Eigen::Vector2d factor1;
-        Eigen::Matrix2d const &J = mem.getJinv(k);
-        for (size_t i = 0; i < nodes.size(); ++i)
-        {
-            std::vector<double> &dffi = cache.dff[k][i];
-            factor1 = J * Eigen::Vector2d(dffi.data());
-            qV(i) += factor1.dot(flux) * gauss.w[k] * detJ;
-        }
+        // Elementary flux vector
+        qV +=  (fk *gradk).transpose() * mem.getJinv(k) * dN * gauss.w[k] * mem.getDetJ(k);
     }
 }
 
 /**
- *  calculation of int_V -[fct2]gradu dV
+ * @brief Compute flux
+ * 
+ * qV_i(3) = int -[f] gradu dV
+ * @authors Romain Boman
  */
 void Tri3::computeqV(std::vector<double> const &u, Eigen::VectorXd &qV, Fct2 const &fct)
 {
@@ -490,6 +461,7 @@ void Tri3::computeqV(std::vector<double> const &u, Eigen::VectorXd &qV, Fct2 con
     GaussTri3 &gauss = cache.gauss;
     MemTri3 &mem = getMem();
 
+    // Gauss integration
     qV = Eigen::Vector2d::Zero();
     for (size_t k = 0; k < gauss.p.size(); ++k)
     {
@@ -498,16 +470,15 @@ void Tri3::computeqV(std::vector<double> const &u, Eigen::VectorXd &qV, Fct2 con
         computeGrad(u, gradk, k);
         Eigen::MatrixXd fk(2, 2);
         fct.eval(*this, u, k, fk, false);
-        double detJ = mem.getDetJ(k);
 
-        qV -= fk * gradk * gauss.w[k] * detJ; // qV = qV + fk.wG.detJ
+        qV -= fk * gradk * gauss.w[k] * mem.getDetJ(k);
     }
 }
 
 /**
- * @brief Compute intergal of function
+ * @brief Compute intergal of scalar function
  * 
- * I = int fct dV
+ * I = int f dV
  * @authors Romain Boman
  */
 double Tri3::computeV(std::vector<double> const &u, Fct0 const &fct)
@@ -516,34 +487,42 @@ double Tri3::computeV(std::vector<double> const &u, Fct0 const &fct)
     GaussTri3 &gauss = cache.gauss;
     MemTri3 &mem = getMem();
 
+    // Gauss integration
     double V = 0.0;
     for (size_t k = 0; k < gauss.p.size(); ++k)
-    {
-        // Function evaluation
-        double fk = fct.eval(*this, u, k);
-        double detJ = mem.getDetJ(k);
-        V += fk * gauss.w[k] * detJ;
-    }
+        V += fct.eval(*this, u, k) * gauss.w[k] * mem.getDetJ(k);
     return V;
 }
+
+/**
+ * @brief Compute intergal of matrix function
+ * 
+ * I = int [f] dV
+ * @authors Romain Boman
+ */
 void Tri3::computeV(std::vector<double> const &u, Eigen::MatrixXd &out, Fct2 const &fct)
 {
     CacheTri3 &cache = getCache();
     GaussTri3 &gauss = cache.gauss;
     MemTri3 &mem = getMem();
 
-    out = Eigen::MatrixXd::Zero(2, 2); // todo out should be resized to match fk size
+    // Gauss integration
+    out = Eigen::MatrixXd::Zero(2, 2); /* @todo out should be resized to match fk size */
     for (size_t k = 0; k < gauss.p.size(); ++k)
     {
         // Function evaluation
         Eigen::MatrixXd fk;
         fct.eval(*this, u, k, fk, false);
-        double detJ = mem.getDetJ(k);
 
-        out += fk * gauss.w[k] * detJ; // [out] = [out] + [fk].wG.detJ
+        out += fk * gauss.w[k] * mem.getDetJ(k);
     }
 }
 
+/**
+ * @brief ???
+ * @todo never used, should be removed
+ * @authors Romain Boman
+ */
 void Tri3::iso_coordinates(Pt x, double eta, double dzeta)
 {
     Eigen::Vector2d iso, b;
@@ -602,11 +581,10 @@ void Tri3::iso_coordinates(Pt x, double eta, double dzeta)
 }
 
 /**
- * @brief Return the element volume
+ * @brief Return the element surface
  * @authors Romain Boman
  */
 double Tri3::computeV()
 {
-    MemTri3 &mem = getMem();
-    return mem.getVol();
+    return getMem().getVol();
 }
diff --git a/tbox/src/wTri3.h b/tbox/src/wTri3.h
index d6b843c1..2102c993 100644
--- a/tbox/src/wTri3.h
+++ b/tbox/src/wTri3.h
@@ -40,7 +40,7 @@ class TBOX_API Tri3 : public Element
     virtual void build(MATTYPE type, Eigen::MatrixXd &A, std::vector<double> const &u, Fct0 const &fct);
     virtual void buildK(Eigen::MatrixXd &K, std::vector<double> const &u, Fct0 const &fct) override;
     virtual void buildK(Eigen::MatrixXd &K, std::vector<double> const &u, Fct2 const &fct, bool fake) override;
-    virtual void buildK_linElastic(Eigen::MatrixXd &K, Eigen::MatrixXd const &H) override;
+    virtual void buildK_mechanical(Eigen::MatrixXd &K, Eigen::MatrixXd const &H) override;
     virtual void builds(Eigen::VectorXd &s, std::vector<double> const &u, Fct0 const &f) override;
     virtual void builds(Eigen::VectorXd &s, std::vector<double> const &u, Fct1 const &f) override;
     virtual void buildDK(Eigen::MatrixXd &K, std::vector<double> const &u, Fct0 const &fct) override;
-- 
GitLab