diff --git a/src/language/modules/LocalFSIModule.cpp b/src/language/modules/LocalFSIModule.cpp
index 98d8d86cf98c26faf0975ea03c65ae3a6abe9fa5..3ed298e6e6ad59e51a123171f9ba5ddd5f0d20c9 100644
--- a/src/language/modules/LocalFSIModule.cpp
+++ b/src/language/modules/LocalFSIModule.cpp
@@ -223,6 +223,7 @@ LocalFSIModule::LocalFSIModule()
                                  const std::shared_ptr<const DiscreteFunctionVariant>& aL,
                                  const std::shared_ptr<const DiscreteFunctionVariant>& aT,
                                  const std::shared_ptr<const DiscreteFunctionVariant>& sigma,
+                                 const std::shared_ptr<const DiscreteFunctionVariant>& p,
                                  const std::vector<std::shared_ptr<const IBoundaryConditionDescriptor>>&
                                    bc_descriptor_list,
                                  const std::shared_ptr<const DiscreteFunctionVariant>& chi_solid,
@@ -236,7 +237,7 @@ LocalFSIModule::LocalFSIModule()
                                 return Order2HyperelasticSolverHandler{getCommonMesh({rho, u, E, CG, aL, aT, sigma})}
                                   .solver()
                                   .apply(Order2HyperelasticSolverHandler::SolverType::Eucclhyd, 1, dt, rho, u, E, CG, aL, aT,
-                                         sigma, bc_descriptor_list, chi_solid, lambda, mu, 0, 0, 0, 0);
+                                         sigma, p, bc_descriptor_list, chi_solid, lambda, mu, 0, 0, 0, 0);
                               }
 
                               ));
@@ -251,6 +252,7 @@ LocalFSIModule::LocalFSIModule()
                                  const std::shared_ptr<const DiscreteFunctionVariant>& aL,
                                  const std::shared_ptr<const DiscreteFunctionVariant>& aT,
                                  const std::shared_ptr<const DiscreteFunctionVariant>& sigma,
+                                 const std::shared_ptr<const DiscreteFunctionVariant>& p,
                                  const std::vector<std::shared_ptr<const IBoundaryConditionDescriptor>>&
                                    bc_descriptor_list,
                                  const std::shared_ptr<const DiscreteFunctionVariant>& chi_solid,
@@ -266,7 +268,7 @@ LocalFSIModule::LocalFSIModule()
                                 return Order2HyperelasticSolverHandler{getCommonMesh({rho, u, E, CG, aL, aT, sigma})}
                                   .solver()
                                   .apply(Order2HyperelasticSolverHandler::SolverType::Eucclhyd, 1, dt, rho, u, E, CG, aL, aT,
-                                         sigma, bc_descriptor_list, chi_solid, lambda, mu, gamma, p_inf, 0, 0);
+                                         sigma, p, bc_descriptor_list, chi_solid, lambda, mu, gamma, p_inf, 0, 0);
                               }
 
                               ));
@@ -281,6 +283,7 @@ LocalFSIModule::LocalFSIModule()
                                  const std::shared_ptr<const DiscreteFunctionVariant>& aL,
                                  const std::shared_ptr<const DiscreteFunctionVariant>& aT,
                                  const std::shared_ptr<const DiscreteFunctionVariant>& sigma,
+                                 const std::shared_ptr<const DiscreteFunctionVariant>& p,
                                  const std::vector<std::shared_ptr<const IBoundaryConditionDescriptor>>&
                                    bc_descriptor_list,
                                  const std::shared_ptr<const DiscreteFunctionVariant>& chi_solid,
@@ -298,7 +301,7 @@ LocalFSIModule::LocalFSIModule()
                                 return Order2HyperelasticSolverHandler{getCommonMesh({rho, u, E, CG, aL, aT, sigma})}
                                   .solver()
                                   .apply(Order2HyperelasticSolverHandler::SolverType::Eucclhyd, 2, dt, rho, u, E, CG, aL, aT,
-                                         sigma, bc_descriptor_list, chi_solid, lambda, mu, gamma_f, p_inf_f, gamma_s, p_inf_s);
+                                         sigma, p, bc_descriptor_list, chi_solid, lambda, mu, gamma_f, p_inf_f, gamma_s, p_inf_s);
                               }
 
                               ));
diff --git a/src/scheme/Order2AcousticSolver.cpp b/src/scheme/Order2AcousticSolver.cpp
index c8f2d9e7bde77263421e5999584c16195a9e1afb..0c2c166ef77412a986d594f65c25373df544a1cf 100644
--- a/src/scheme/Order2AcousticSolver.cpp
+++ b/src/scheme/Order2AcousticSolver.cpp
@@ -410,7 +410,6 @@ class Order2AcousticSolverHandler::Order2AcousticSolver final : public Order2Aco
   _vector_limiter(const MeshType& mesh,
                   const DiscreteFunctionP0<const Rd>& f,
                   DiscreteFunctionDPk<Dimension, Rd>& DPK_fh,
-                  //const DiscreteFunctionP0<const double>& p,
                   const DiscreteFunctionDPk<Dimension, const double>& DPk_ph) const 
   {
     MeshData<MeshType>& mesh_data = MeshDataManager::instance().getMeshData(mesh);
@@ -421,30 +420,25 @@ class Order2AcousticSolverHandler::Order2AcousticSolver final : public Order2Aco
     
     const auto xj = mesh_data.xj();
 
-    //Calcul du gradiant
     CellValue<Rd> n{mesh.connectivity()};
     parallel_for(
       mesh.numberOfCells(), PUGS_LAMBDA(const CellId cell_id) {
         auto coefficients_p = DPk_ph.coefficients(cell_id);
         Rd grad_p = zero;
         for(size_t i = 1; i < coefficients_p.size(); ++i){
-          grad_p[i] = coefficients_p[i];
+          grad_p[i-1] = coefficients_p[i];
         }
         const double norm_grad_p = l2Norm(grad_p);
         if(norm_grad_p == 0){
           n[cell_id] = zero;
-        }
-        else{
-          for(size_t d = 0; d < Dimension; ++d){
-            n[cell_id][d] = grad_p[d] / norm_grad_p;
-          }
+        } 
+        else {
+          n[cell_id] = (1/norm_grad_p) * grad_p;
         }
 
         
       });
 
-
-    //Construction des vecteurs orthogonaux
     const CellValue<Rd> t{mesh.connectivity()};
     const CellValue<Rd> l{mesh.connectivity()};
     parallel_for(
@@ -466,9 +460,7 @@ class Order2AcousticSolverHandler::Order2AcousticSolver final : public Order2Aco
           tj = zero;
         }
         else {
-          for(size_t d = 0; d < Dimension; ++d){
-            tj[d] = tj[d] / norm_tj;
-          }
+          tj = (1/norm_tj) * tj;
         }
         t[cell_id] = tj;
 
@@ -478,14 +470,11 @@ class Order2AcousticSolverHandler::Order2AcousticSolver final : public Order2Aco
           lj[1] = nj[2]*tj[0] - nj[0]*tj[2];
           lj[2] = nj[0]*tj[1] - nj[1]*tj[0];
           const double& norm_lj = l2Norm(lj);
-          for(size_t d = 0; d < Dimension; ++d){
-            lj[d] = lj[d] / norm_lj;
-          }
+          lj = (1/norm_lj) * lj;
         }
         l[cell_id] = lj;
       });
 
-    //Limiteurs
     parallel_for(
       mesh.numberOfCells(), PUGS_LAMBDA(const CellId cell_id){
         const double fn = dot(f[cell_id],n[cell_id]);
diff --git a/src/scheme/Order2HyperelasticSolver.cpp b/src/scheme/Order2HyperelasticSolver.cpp
index ec3ec68c8914b6b359bf484a278d102e1ecf726a..6875c5005faaf096a2b61a0625a29a9ed389057f 100644
--- a/src/scheme/Order2HyperelasticSolver.cpp
+++ b/src/scheme/Order2HyperelasticSolver.cpp
@@ -335,214 +335,368 @@ class Order2HyperelasticSolverHandler::Order2HyperelasticSolver final
     return u;
   }
 
+    NodeValue<Rd>
+  _computeBr(const Mesh<Dimension>& mesh,
+             const NodeValuePerCell<const Rdxd>& Ajr,
+             const DiscreteVectorFunction& u,
+             const DiscreteTensorFunction& sigma) const
+  {
+    MeshDataType& mesh_data = MeshDataManager::instance().getMeshData(mesh);
+
+    const NodeValuePerCell<const Rd>& Cjr = mesh_data.Cjr();
+
+    const auto& node_to_cell_matrix               = mesh.connectivity().nodeToCellMatrix();
+    const auto& node_local_numbers_in_their_cells = mesh.connectivity().nodeLocalNumbersInTheirCells();
+
+    NodeValue<Rd> b{mesh.connectivity()};
+
+    parallel_for(
+      mesh.numberOfNodes(), PUGS_LAMBDA(NodeId r) {
+        const auto& node_to_cell                   = node_to_cell_matrix[r];
+        const auto& node_local_number_in_its_cells = node_local_numbers_in_their_cells.itemArray(r);
+
+        Rd br = zero;
+        for (size_t j = 0; j < node_to_cell.size(); ++j) {
+          const CellId J       = node_to_cell[j];
+          const unsigned int R = node_local_number_in_its_cells[j];
+          br += Ajr(J, R) * u[J] - sigma[J] * Cjr(J, R);
+        }
+
+        b[r] = br;
+      });
+
+    return b;
+  }
+
   NodeValuePerCell<Rd>
+  _computeFjr(const MeshType& mesh,
+              const NodeValuePerCell<const Rdxd>& Ajr,
+              const NodeValue<const Rd>& ur,
+              const DiscreteVectorFunction& u,
+              const DiscreteTensorFunction& sigma) const
+  {
+    MeshDataType& mesh_data = MeshDataManager::instance().getMeshData(mesh);
+
+    const NodeValuePerCell<const Rd> Cjr = mesh_data.Cjr();
+
+    const auto& cell_to_node_matrix = mesh.connectivity().cellToNodeMatrix();
+
+    NodeValuePerCell<Rd> F{mesh.connectivity()};
+    parallel_for(
+      mesh.numberOfCells(), PUGS_LAMBDA(CellId j) {
+        const auto& cell_nodes = cell_to_node_matrix[j];
+
+        for (size_t r = 0; r < cell_nodes.size(); ++r) {
+          F(j, r) = -Ajr(j, r) * (u[j] - ur[cell_nodes[r]]) + sigma[j] * Cjr(j, r);
+        }
+      });
+
+    return F;
+  }
+
+  NodeValue<Rd>
+  _computeBr(const Mesh<Dimension>& mesh,
+             const NodeValuePerCell<const Rdxd>& Ajr,
+             DiscreteFunctionDPk<Dimension, const Rd> DPk_u,
+             DiscreteFunctionDPk<Dimension, const Rdxd> DPk_S,
+             DiscreteFunctionDPk<Dimension, const double> DPk_p,
+             CellValue<double> lambda, NodeValuePerCell<double> coef) const
+  {
+    MeshDataType& mesh_data = MeshDataManager::instance().getMeshData(mesh);
+
+    const NodeValuePerCell<const Rd>& Cjr = mesh_data.Cjr();
+    const auto& xr                        = mesh.xr();
+    const TinyMatrix<Dimension> I = identity;
+
+    const auto& node_to_cell_matrix               = mesh.connectivity().nodeToCellMatrix();
+    const auto& node_local_numbers_in_their_cells = mesh.connectivity().nodeLocalNumbersInTheirCells();
+
+    NodeValue<Rd> b{mesh.connectivity()};
+
+    parallel_for(
+      mesh.numberOfNodes(), PUGS_LAMBDA(NodeId r) {
+        const auto& node_to_cell                   = node_to_cell_matrix[r];
+        const auto& node_local_number_in_its_cells = node_local_numbers_in_their_cells.itemArray(r);
+
+        Rd br = zero;
+        for (size_t j = 0; j < node_to_cell.size(); ++j) {
+          const CellId J       = node_to_cell[j];
+          const unsigned int R = node_local_number_in_its_cells[j];
+          const Rdxd sigma_r = sqrt(lambda[J]+(1-lambda[J])*coef(J,R))*DPk_S[J](xr[r]) - DPk_p[J](xr[r])*I;
+
+          br += Ajr(J, R) * DPk_u[J](xr[r]) - sigma_r * Cjr(J, R);
+        }
+
+        b[r] = br;
+      });
+
+    return b;
+  }
+
+    NodeValuePerCell<Rd>
   _computeFjr(const MeshType& mesh,
               const NodeValuePerCell<const Rdxd>& Ajr,
               const NodeValue<const Rd>& ur,
               DiscreteFunctionDPk<Dimension, const Rd> DPk_uh,
-              DiscreteFunctionDPk<Dimension, const Rdxd> DPk_sigma) const
+              DiscreteFunctionDPk<Dimension, const Rdxd> DPk_S,
+              DiscreteFunctionDPk<Dimension, const double> DPk_p,
+              CellValue<double> lambda, NodeValuePerCell<double> coef) const
   {
     MeshDataType& mesh_data = MeshDataManager::instance().getMeshData(mesh);
 
     const NodeValuePerCell<const Rd> Cjr = mesh_data.Cjr();
     const NodeValue<const Rd>& xr        = mesh.xr();
-
-    //const auto& node_to_cell_matrix               = mesh.connectivity().nodeToCellMatrix();
-    //const auto& node_local_numbers_in_their_cells = mesh.connectivity().nodeLocalNumbersInTheirCells();
+    const TinyMatrix<Dimension> I = identity;
 
     const auto& cell_to_node_matrix = mesh.connectivity().cellToNodeMatrix();
 
     NodeValuePerCell<Rd> F{mesh.connectivity()};
-    //parallel_for(
-    //  mesh.numberOfNodes(), PUGS_LAMBDA(NodeId r) {
-    //    const auto& node_to_cell                   = node_to_cell_matrix[r];
-    //    const auto& node_local_number_in_its_cells = node_local_numbers_in_their_cells.itemArray(r);
-    //
-    //    for (size_t j = 0; j < node_to_cell.size(); ++j) {
-    //      const CellId J       = node_to_cell[j];
-    //      const unsigned int R = node_local_number_in_its_cells[j];
-    //      F(J, R)              = -Ajr(J, R) * (DPk_uh[J](xr[r]) - ur[r]) + DPk_sigma[J](xr[r]) * Cjr(J, R);
-    //    }
-    //  });
 
     parallel_for(
       mesh.numberOfCells(), PUGS_LAMBDA(CellId j) {
         const auto& cell_nodes = cell_to_node_matrix[j];
 
         for(size_t r = 0; r < cell_nodes.size(); ++r) {
-          F(j,r) = -Ajr(j,r) * (DPk_uh[j](xr[cell_nodes[r]]) - ur[cell_nodes[r]]) + DPk_sigma[j](xr[cell_nodes[r]])*Cjr(j,r);
+          Rdxd sigma_r = sqrt(lambda[j]+(1-lambda[j])*coef(j,r))*DPk_S[j](xr[cell_nodes[r]]) - DPk_p[j](xr[cell_nodes[r]])*I;
+          F(j,r) = -Ajr(j,r) * (DPk_uh[j](xr[cell_nodes[r]]) - ur[cell_nodes[r]]) + sigma_r*Cjr(j,r);
         }
       });
 
     return F;
   }
 
-  void
-  _tensor_limiter(const MeshType& mesh,
-                  const DiscreteFunctionP0<const Rdxd>& f,
-                  DiscreteFunctionDPk<Dimension, Rdxd>& DPk_fh) const
+void
+  _scalar_limiter(const MeshType& mesh,
+                  const DiscreteFunctionP0<const double>& f,
+                  DiscreteFunctionDPk<Dimension, double>& DPk_fh) const
   {
     MeshData<MeshType>& mesh_data = MeshDataManager::instance().getMeshData(mesh);
     StencilManager::BoundaryDescriptorList symmetry_boundary_descriptor_list;
     StencilDescriptor stencil_descriptor{1, StencilDescriptor::ConnectionType::by_nodes};
-    auto stencil = StencilManager::instance().getCellToCellStencilArray(mesh.connectivity(), stencil_descriptor,
-                                                                        symmetry_boundary_descriptor_list);
+    auto stencil = StencilManager::instance().getCellToCellStencilArray(mesh.connectivity(), stencil_descriptor, symmetry_boundary_descriptor_list);
 
     const auto xj = mesh_data.xj();
 
-    parallel_for(
-      mesh.numberOfCells(), PUGS_LAMBDA(const CellId cell_id) {
-        const Rdxd fj = f[cell_id];
+    CellValue<double> alph_J2{mesh.connectivity()};
 
-        Rdxd f_min = fj;
-        Rdxd f_max = fj;
+    parallel_for(mesh.numberOfCells(), PUGS_LAMBDA(const CellId cell_id){
+      const double fj = f[cell_id];
 
-        const auto cell_stencil = stencil[cell_id];
-        for (size_t i_cell = 0; i_cell < cell_stencil.size(); ++i_cell) {
-          for (size_t row = 0; row < Dimension; ++row) {
-            for (size_t col = 0; col < Dimension; ++col) {
-              f_min(row, col) = std::min(f_min(row, col), f[cell_stencil[i_cell]](row, col));
-              f_max(row, col) = std::max(f_max(row, col), f[cell_stencil[i_cell]](row, col));
-            }
-          }
-        }
+      double f_min = fj;
+      double f_max = fj;
 
-        Rdxd f_bar_min = fj;
-        Rdxd f_bar_max = fj;
+      const auto cell_stencil = stencil[cell_id];
+      for(size_t i_cell = 0; i_cell < cell_stencil.size(); ++i_cell){
+        f_min = std::min(f_min, f[cell_stencil[i_cell]]);
+        f_max = std::max(f_max, f[cell_stencil[i_cell]]);
+      }
 
-        for (size_t i_cell = 0; i_cell < cell_stencil.size(); ++i_cell) {
-          const CellId cell_k_id = cell_stencil[i_cell];
-          const Rdxd f_xk        = DPk_fh[cell_id](xj[cell_k_id]);
+      double f_bar_min = fj;
+      double f_bar_max = fj;
 
-          for (size_t row = 0; row < Dimension; ++row) {
-            for (size_t col = 0; col < Dimension; ++col) {
-              f_bar_min(row, col) = std::min(f_bar_min(row, col), f_xk(row, col));
-              f_bar_max(row, col) = std::max(f_bar_max(row, col), f_xk(row, col));
-            }
-          }
-        }
+      for(size_t i_cell = 0; i_cell < cell_stencil.size(); ++i_cell){
+        const CellId cell_k_id = cell_stencil[i_cell];
+        const double f_xk    = DPk_fh[cell_id](xj[cell_k_id]);
 
-        const double eps = 1E-14;
-        Rdxd coef1;
-        for (size_t row = 0; row < Dimension; ++row) {
-          for (size_t col = 0; col < Dimension; ++col) {
-            coef1(row, col) = 1;
-            if (std::abs(f_bar_max(row, col) - fj(row, col)) > eps) {
-              coef1(row, col) = (f_max(row, col) - fj(row, col)) / (f_bar_max(row, col) - fj(row, col));
-            }
-          }
-        }
+        f_bar_min = std::min(f_bar_min, f_xk);
+        f_bar_max = std::max(f_bar_max, f_xk);
+      }
 
-        Rdxd coef2;
-        for (size_t row = 0; row < Dimension; ++row) {
-          for (size_t col = 0; col < Dimension; ++col) {
-            coef2(row, col) = 1;
-            if (std::abs(f_bar_min(row, col) - fj(row, col)) > eps) {
-              coef2(row, col) = (f_min(row, col) - fj(row, col)) / ((f_bar_min(row, col) - fj(row, col)));
-            }
-          }
-        }
+      const double eps = 1E-14;
+      double coef1     = 1;
+      if (std::abs(f_bar_max - fj) > eps) {
+        coef1 = (f_max - fj) / ((f_bar_max - fj));
+      }
 
-        double min_coef1 = coef1(0, 0);
-        double min_coef2 = coef2(0, 0);
-        for (size_t row = 0; row < Dimension; ++row) {
-          for (size_t col = 0; col < Dimension; ++col) {
-            min_coef1 = std::min(min_coef1, coef1(row, col));
-            min_coef2 = std::min(min_coef2, coef2(row, col));
-          }
-        }
+      double coef2 = 1.;
+      if (std::abs(f_bar_min - fj) > eps) {
+        coef2 = (f_min - fj) / ((f_bar_min - fj));
+      }
 
-        const double lambda = std::max(0., std::min(1., std::min(min_coef1, min_coef2)));
+      const double lambda = std::max(0., std::min(1., std::min(coef1, coef2)));
+      alph_J2[cell_id] = lambda;
 
-        auto coefficients = DPk_fh.coefficients(cell_id);
+      auto coefficients = DPk_fh.coefficients(cell_id);
 
-        coefficients[0] = (1 - lambda) * f[cell_id] + lambda * coefficients[0];
-        for (size_t i = 1; i < coefficients.size(); ++i) {
-          coefficients[i] *= lambda;
-        }
-      });
+      coefficients[0] = (1 - lambda) * f[cell_id] + lambda * coefficients[0];
+      for (size_t i = 1; i < coefficients.size(); ++i) {
+        coefficients[i] *= lambda;
+      }
+    });
   }
 
-  void
+  void 
   _vector_limiter(const MeshType& mesh,
                   const DiscreteFunctionP0<const Rd>& f,
-                  DiscreteFunctionDPk<Dimension, Rd>& DPk_fh) const
+                  DiscreteFunctionDPk<Dimension, Rd>& DPK_fh,
+                  const DiscreteFunctionDPk<Dimension, const double>& DPk_ph) const 
   {
     MeshData<MeshType>& mesh_data = MeshDataManager::instance().getMeshData(mesh);
     StencilManager::BoundaryDescriptorList symmetry_boundary_descriptor_list;
     StencilDescriptor stencil_descriptor{1, StencilDescriptor::ConnectionType::by_nodes};
     auto stencil = StencilManager::instance().getCellToCellStencilArray(mesh.connectivity(), stencil_descriptor,
                                                                         symmetry_boundary_descriptor_list);
-
+    
     const auto xj = mesh_data.xj();
 
+    CellValue<Rd> n{mesh.connectivity()};
     parallel_for(
       mesh.numberOfCells(), PUGS_LAMBDA(const CellId cell_id) {
-        const Rd fj = f[cell_id];
+        auto coefficients_p = DPk_ph.coefficients(cell_id);
+        Rd grad_p = zero;
+        for(size_t i = 1; i < coefficients_p.size(); ++i){
+          grad_p[i-1] = coefficients_p[i];
+        }
+        const double norm_grad_p = l2Norm(grad_p);
+        if(norm_grad_p == 0){
+          n[cell_id] = zero;
+        } 
+        else {
+          n[cell_id] = (1/norm_grad_p) * grad_p;
+        }
 
-        Rd f_min = fj;
-        Rd f_max = fj;
+        
+      });
 
-        const auto cell_stencil = stencil[cell_id];
-        for (size_t i_cell = 0; i_cell < cell_stencil.size(); ++i_cell) {
-          for (size_t dim = 0; dim < Dimension; ++dim) {
-            f_min[dim] = std::min(f_min[dim], f[cell_stencil[i_cell]][dim]);
-            f_max[dim] = std::max(f_max[dim], f[cell_stencil[i_cell]][dim]);
+    const CellValue<Rd> t{mesh.connectivity()};
+    const CellValue<Rd> l{mesh.connectivity()};
+    parallel_for(
+      mesh.numberOfCells(), PUGS_LAMBDA(const CellId cell_id) {
+        const Rd nj = n[cell_id];
+        Rd a = zero;
+        if(l2Norm(nj) != 0){
+          if((nj[0] / l2Norm(nj) != 1) and (nj[0] / l2Norm(nj) != -1)){
+            a[0] = 1.;
           }
+          else { 
+            a[1] = 1.;
+          }
+        }
+
+        Rd tj = a - dot(a,nj) * nj;
+        const double& norm_tj = l2Norm(tj);
+        if(norm_tj == 0){
+          tj = zero;
+        }
+        else {
+          tj = (1/norm_tj) * tj;
+        }
+        t[cell_id] = tj;
+
+        Rd lj = zero;
+        if(Dimension == 3){
+          lj[0] = nj[1]*tj[2] - nj[2]*tj[1];
+          lj[1] = nj[2]*tj[0] - nj[0]*tj[2];
+          lj[2] = nj[0]*tj[1] - nj[1]*tj[0];
+          const double& norm_lj = l2Norm(lj);
+          if(norm_lj != 0){
+            lj = (1/norm_lj) * lj;
+          }
+            
+        }
+        l[cell_id] = lj;
+      });
+
+    parallel_for(
+      mesh.numberOfCells(), PUGS_LAMBDA(const CellId cell_id){
+        const double fn = dot(f[cell_id],n[cell_id]);
+        const double ft = dot(f[cell_id],t[cell_id]);
+        const double fl = dot(f[cell_id],l[cell_id]);
+
+        double fn_min = fn;
+        double fn_max = fn;
+        double ft_min = ft;
+        double ft_max = ft;
+        double fl_min = fl;
+        double fl_max = fl;
+
+        const auto cell_stencil = stencil[cell_id];
+        for(size_t i_cell = 0; i_cell < cell_stencil.size(); ++i_cell){
+          const double fn_k = dot(f[cell_stencil[i_cell]],n[cell_stencil[i_cell]]);
+          fn_min            = std::min(fn_min,fn_k);
+          fn_max            = std::max(fn_max,fn_k);
+
+          const double ft_k = dot(f[cell_stencil[i_cell]],t[cell_stencil[i_cell]]);
+          ft_min            = std::min(ft_min,ft_k);
+          ft_max            = std::max(ft_max,ft_k);
+
+          const double fl_k = dot(f[cell_stencil[i_cell]],l[cell_stencil[i_cell]]);
+          fl_min            = std::min(fl_min,fl_k);
+          fl_max            = std::max(fl_max,fl_k);
         }
 
-        Rd f_bar_min = fj;
-        Rd f_bar_max = fj;
+        double fn_bar_min = fn;
+        double fn_bar_max = fn;
+        double ft_bar_min = ft;
+        double ft_bar_max = ft;
+        double fl_bar_min = fl;
+        double fl_bar_max = fl;
 
-        for (size_t i_cell = 0; i_cell < cell_stencil.size(); ++i_cell) {
+        for(size_t i_cell = 0; i_cell < cell_stencil.size(); ++i_cell){
           const CellId cell_k_id = cell_stencil[i_cell];
-          const Rd f_xk          = DPk_fh[cell_id](xj[cell_k_id]);
+          const Rd f_xk          = DPK_fh[cell_id](xj[cell_k_id]);
 
-          for (size_t dim = 0; dim < Dimension; ++dim) {
-            f_bar_min[dim] = std::min(f_bar_min[dim], f_xk[dim]);
-            f_bar_max[dim] = std::max(f_bar_max[dim], f_xk[dim]);
-          }
+          const double fn_xk = dot(f_xk,n[cell_k_id]);
+          fn_bar_min         = std::min(fn_bar_min,fn_xk);
+          fn_bar_max         = std::max(fn_bar_max,fn_xk);
+
+          const double ft_xk = dot(f_xk,t[cell_k_id]);
+          ft_bar_min         = std::min(ft_bar_min,ft_xk);
+          ft_bar_max         = std::max(ft_bar_max,ft_xk);
+
+          const double fl_xk = dot(f_xk,l[cell_k_id]);
+          fl_bar_min         = std::min(fl_bar_min,fl_xk);
+          fl_bar_max         = std::max(fl_bar_max,fl_xk);
         }
 
         const double eps = 1E-14;
-        Rd coef1;
-        for (size_t dim = 0; dim < Dimension; ++dim) {
-          coef1[dim] = 1;
-          if (std::abs(f_bar_max[dim] - fj[dim]) > eps) {
-            coef1[dim] = (f_max[dim] - fj[dim]) / ((f_bar_max[dim] - fj[dim]));
-          }
+        double coef1_n   = 1;
+        if(std::abs(fn_bar_max - fn) > eps){
+          coef1_n = (fn_max - fn) / (fn_bar_max - fn);
+        } 
+        double coef2_n = 1;
+        if(std::abs(fn_bar_min - fn) > eps){
+          coef2_n = (fn_min - fn) / (fn_bar_min - fn);
         }
-
-        Rd coef2;
-        for (size_t dim = 0; dim < Dimension; ++dim) {
-          coef2[dim] = 1;
-          if (std::abs(f_bar_min[dim] - fj[dim]) > eps) {
-            coef2[dim] = (f_min[dim] - fj[dim]) / ((f_bar_min[dim] - fj[dim]));
-          }
+        
+        double coef1_t = 1;
+        if(std::abs(ft_bar_max - ft) > eps){
+          coef1_t = (ft_max - ft) / (ft_bar_max - ft);
         }
-
-        double min_coef1 = coef1[0];
-        double min_coef2 = coef2[0];
-        for (size_t dim = 1; dim < Dimension; ++dim) {
-          min_coef1 = std::min(min_coef1, coef1[dim]);
-          min_coef2 = std::min(min_coef2, coef2[dim]);
+        double coef2_t = 1;
+        if(std::abs(ft_bar_min - ft) > eps){
+          coef2_t = (ft_min - ft) / (ft_bar_min - ft);
         }
 
-        const double lambda = std::max(0., std::min(1., std::min(min_coef1, min_coef2)));
-
-        auto coefficients = DPk_fh.coefficients(cell_id);
+        double coef1_l = 1;
+        if(std::abs(fl_bar_max - fl) > eps){
+          coef1_l = (fl_max - fl) / (fl_bar_max - fl);
+        }
+        double coef2_l = 1;
+        if(std::abs(fl_bar_min - fl) > eps){
+          coef2_l = (fl_min - fl) / (fl_bar_min - fl);
+        }
 
-        coefficients[0] = (1 - lambda) * f[cell_id] + lambda * coefficients[0];
-        for (size_t i = 1; i < coefficients.size(); ++i) {
-          coefficients[i] *= lambda;
+        const double lambda_n = std::max(0., std::min(1., std::min(coef1_n,coef2_n)));
+        const double lambda_t = std::max(0., std::min(1., std::min(coef1_t,coef2_t)));
+        const double lambda_l = std::max(0., std::min(1., std::min(coef1_l,coef2_l)));
+
+        auto coefficients = DPK_fh.coefficients(cell_id);
+        coefficients[0] = (1 - lambda_n)*fn*n[cell_id] + lambda_n*dot(coefficients[0],n[cell_id])*n[cell_id] 
+                        + (1 - lambda_t)*ft*t[cell_id] + lambda_t*dot(coefficients[0],t[cell_id])*t[cell_id] 
+                        + (1 - lambda_l)*fl*l[cell_id] + lambda_l*dot(coefficients[0],l[cell_id])*l[cell_id];
+        for(size_t i = 1; i < coefficients.size(); ++i){
+          coefficients[i] = lambda_n*dot(coefficients[i],n[cell_id])*n[cell_id] 
+                          + lambda_t*dot(coefficients[i],t[cell_id])*t[cell_id] 
+                          + lambda_l*dot(coefficients[i],l[cell_id])*l[cell_id];
         }
-      });
+    });
   }
 
-  CellValue<double>
-  _scalar_limiter_coefficient(const MeshType& mesh,
-                              const DiscreteFunctionP0<const double>& f,
-                              const DiscreteFunctionDPk<Dimension, const double>& DPk_fh) const
+  CellValue<double> 
+  _matrix_limiter(const MeshType& mesh,
+                  const DiscreteFunctionP0<const Rdxd>& S,
+                  DiscreteFunctionDPk<Dimension, Rdxd>& DPk_Sh) const
   {
     MeshData<MeshType>& mesh_data = MeshDataManager::instance().getMeshData(mesh);
     StencilManager::BoundaryDescriptorList symmetry_boundary_descriptor_list;
@@ -552,49 +706,71 @@ class Order2HyperelasticSolverHandler::Order2HyperelasticSolver final
 
     const auto xj = mesh_data.xj();
 
-    CellValue<double> lambda{mesh.connectivity()};
+    //A retirer + tard
+    const auto xr = mesh.xr();
+    const auto& cell_to_node_matrix = mesh.connectivity().cellToNodeMatrix();
+    //
 
+    CellValue<double> lambda{mesh.connectivity()};
+    const DiscreteScalarFunction& inv2 = 0.5*trace(transpose(S)*S);
     parallel_for(
-      mesh.numberOfCells(), PUGS_LAMBDA(const CellId cell_id) {
-        const double fj = f[cell_id];
-
-        double f_min = fj;
-        double f_max = fj;
+      mesh.numberOfCells(), PUGS_LAMBDA(const CellId cell_id){
+        const double inv2j = inv2[cell_id];
+        
+        double inv2_min = inv2j;
+        double inv2_max = inv2j;
 
         const auto cell_stencil = stencil[cell_id];
-        for (size_t i_cell = 0; i_cell < cell_stencil.size(); ++i_cell) {
-          f_min = std::min(f_min, f[cell_stencil[i_cell]]);
-          f_max = std::max(f_max, f[cell_stencil[i_cell]]);
+        for(size_t i_cell = 0; i_cell < cell_stencil.size(); ++i_cell){
+          inv2_min = std::min(inv2_min, inv2[cell_stencil[i_cell]]);
+          inv2_max = std::max(inv2_max, inv2[cell_stencil[i_cell]]);
         }
 
-        double f_bar_min = fj;
-        double f_bar_max = fj;
+        double inv2_bar_min = inv2j;
+        double inv2_bar_max = inv2j;
 
-        for (size_t i_cell = 0; i_cell < cell_stencil.size(); ++i_cell) {
-          const CellId cell_k_id = cell_stencil[i_cell];
-          const double f_xk      = DPk_fh[cell_id](xj[cell_k_id]);
+        const auto& cell_nodes = cell_to_node_matrix[cell_id];
+        for(size_t r = 0; r < cell_nodes.size(); ++r){
+          const double inv2_xr = 0.5*trace(transpose(DPk_Sh[cell_id](xr[cell_nodes[r]]))*DPk_Sh[cell_id](xr[cell_nodes[r]]));
 
-          f_bar_min = std::min(f_bar_min, f_xk);
-          f_bar_max = std::max(f_bar_max, f_xk);
+          inv2_bar_min = std::min(inv2_bar_min, inv2_xr);
+          inv2_bar_max = std::max(inv2_bar_max, inv2_xr);
         }
 
-        const double eps = 1E-14;
-        double coef1     = 1;
-        if (std::abs(f_bar_max - fj) > eps) {
-          coef1 = (f_max - fj) / ((f_bar_max - fj));
+        //for(size_t i_cell = 0; i_cell < cell_stencil.size(); ++i_cell){
+        //  const CellId cell_k_id = cell_stencil[i_cell];
+        //  const double inv2_xk   = 0.5*trace(transpose(DPk_Sh[cell_id](xj[cell_k_id]))*DPk_Sh[cell_id](xj[cell_k_id]));
+//
+        //  inv2_bar_min = std::min(inv2_bar_min, inv2_xk);
+        //  inv2_bar_max = std::max(inv2_bar_max, inv2_xk);
+        //}
+
+        const double eps =  1E-14;
+        double coef1     = 1.;
+        double coef2     = 1.;
+        if(std::abs(inv2_bar_max - inv2j) > eps){
+          coef1 = (inv2_max - inv2j) / (inv2_bar_max - inv2j);
+        } 
+        if(std::abs(inv2_bar_min - inv2j) > eps){
+          coef2 = (inv2_min - inv2j) / (inv2_bar_min - inv2j);
         }
 
-        double coef2 = 1.;
-        if (std::abs(f_bar_min - fj) > eps) {
-          coef2 = (f_min - fj) / ((f_bar_min - fj));
-        }
+        //const double lambda_inv2 = sqrt(std::max(0., std::min(1., std::min(coef1, coef2))));
+        const double lambda_inv2 = std::max(0., std::min(1., std::min(coef1, coef2)));
+        lambda[cell_id] = lambda_inv2;
 
-        lambda[cell_id] = std::max(0., std::min(1., std::min(coef1, coef2)));
-      });
+        //auto coefficients = DPk_Sh.coefficients(cell_id);
+
+        //coefficients[0] = (1-lambda_inv2)*S[cell_id] + lambda_inv2 * coefficients[0];
+        //for (size_t i = 1; i < coefficients.size(); ++i) {
+        //  coefficients[i] *= lambda_inv2;
+        //} 
+    });
     return lambda;
-  }
+  } 
 
   std::tuple<const std::shared_ptr<const DiscreteFunctionVariant>,
+             const std::shared_ptr<const DiscreteFunctionVariant>,
              const std::shared_ptr<const DiscreteFunctionVariant>,
              const std::shared_ptr<const DiscreteFunctionVariant>>
   _apply_NeoHook(const DiscreteScalarFunction rho,
@@ -616,11 +792,14 @@ class Order2HyperelasticSolverHandler::Order2HyperelasticSolver final
     const DiscreteScalarFunction& aL_d = sqrt(chi_solid * (lambda + 2 * mu) / rho + gamma * (p_d + p_inf) / rho);
     const DiscreteScalarFunction& aT_d = sqrt(chi_solid * mu / rho);
 
-    return {std::make_shared<DiscreteFunctionVariant>(sigma_d), std::make_shared<DiscreteFunctionVariant>(aL_d),
+    return {std::make_shared<DiscreteFunctionVariant>(sigma_d), 
+            std::make_shared<DiscreteFunctionVariant>(p_d),
+            std::make_shared<DiscreteFunctionVariant>(aL_d),
             std::make_shared<DiscreteFunctionVariant>(aT_d)};
   }
 
   std::tuple<const std::shared_ptr<const DiscreteFunctionVariant>,
+             const std::shared_ptr<const DiscreteFunctionVariant>,
              const std::shared_ptr<const DiscreteFunctionVariant>,
              const std::shared_ptr<const DiscreteFunctionVariant>>
   _apply_NeoHook2(const DiscreteScalarFunction rho,
@@ -638,18 +817,21 @@ class Order2HyperelasticSolverHandler::Order2HyperelasticSolver final
 
     const DiscreteScalarFunction& eps = E - 0.5 * dot(u, u);
     const DiscreteScalarFunction& p_d =
-      (1 - chi_solid) * ((gamma_f - 1) * rho * eps) + chi_solid * ((gamma_s - 1.) * rho * eps - gamma_s * p_inf_s);
+      (1 - chi_solid) * ((gamma_f - 1) * rho * eps - gamma_f * p_inf_f) + chi_solid * ((gamma_s - 1.) * rho * eps - gamma_s * p_inf_s);
     const DiscreteTensorFunction& sigma_d =
       chi_solid * 2 * mu / sqrt(det(CG)) * (CG - 1. / 3. * trace(CG) * I) - p_d * I;
     const DiscreteScalarFunction& aL_d = sqrt(
       chi_solid * (2 * mu) / rho + ((1 - chi_solid) * gamma_f * p_d + chi_solid * (gamma_s * (p_d + p_inf_s))) / rho);
     const DiscreteScalarFunction& aT_d = sqrt(chi_solid * mu / rho);
 
-    return {std::make_shared<DiscreteFunctionVariant>(sigma_d), std::make_shared<DiscreteFunctionVariant>(aL_d),
+    return {std::make_shared<DiscreteFunctionVariant>(sigma_d), 
+            std::make_shared<DiscreteFunctionVariant>(p_d),
+            std::make_shared<DiscreteFunctionVariant>(aL_d),
             std::make_shared<DiscreteFunctionVariant>(aT_d)};
   }
 
   std::tuple<const std::shared_ptr<const DiscreteFunctionVariant>,
+             const std::shared_ptr<const DiscreteFunctionVariant>,
              const std::shared_ptr<const DiscreteFunctionVariant>,
              const std::shared_ptr<const DiscreteFunctionVariant>>
   _apply_state_law(const size_t law,
@@ -695,7 +877,7 @@ class Order2HyperelasticSolverHandler::Order2HyperelasticSolver final
     std::shared_ptr mesh_v = getCommonMesh({rho_v, aL_v, aT_v, u_v, sigma_v});
     if (not mesh_v) {
       throw NormalError("discrete functions are not defined on the same mesh");
-    }   //      - p* identity; // - chi_solid*P_zero_air_repo*identity;
+    }
 
     if (not checkDiscretizationType({rho_v, aL_v, u_v, sigma_v}, DiscreteFunctionType::P0)) {
       throw NormalError("hyperelastic solver expects P0 functions");
@@ -708,6 +890,55 @@ class Order2HyperelasticSolverHandler::Order2HyperelasticSolver final
     const DiscreteScalarFunction& aT    = aT_v->get<DiscreteScalarFunction>();
     const DiscreteTensorFunction& sigma = sigma_v->get<DiscreteTensorFunction>();
 
+    NodeValuePerCell<const Rdxd> Ajr = this->_computeAjr(solver_type, mesh, rho * aL, rho * aT);
+
+    NodeValue<Rdxd> Ar = this->_computeAr(mesh, Ajr);
+    NodeValue<Rd> br   = this->_computeBr(mesh, Ajr, u, sigma);
+
+    const BoundaryConditionList bc_list = this->_getBCList(mesh, bc_descriptor_list);
+    this->_applyBoundaryConditions(bc_list, mesh, Ar, br);
+
+    synchronize(Ar);
+    synchronize(br);
+
+    NodeValue<const Rd> ur         = this->_computeUr(mesh, Ar, br);
+    NodeValuePerCell<const Rd> Fjr = this->_computeFjr(mesh, Ajr, ur, u, sigma);
+
+    return std::make_tuple(std::make_shared<const ItemValueVariant>(ur),
+                           std::make_shared<const SubItemValuePerItemVariant>(Fjr));
+  }
+
+  std::tuple<const std::shared_ptr<const ItemValueVariant>, const std::shared_ptr<const SubItemValuePerItemVariant>>
+  compute_fluxes(const SolverType& solver_type,
+                 const std::shared_ptr<const DiscreteFunctionVariant>& rho_v,
+                 const std::shared_ptr<const DiscreteFunctionVariant>& aL_v,
+                 const std::shared_ptr<const DiscreteFunctionVariant>& aT_v,
+                 const std::shared_ptr<const DiscreteFunctionVariant>& u_v,
+                 const std::shared_ptr<const DiscreteFunctionVariant>& sigma_v,
+                 const std::shared_ptr<const DiscreteFunctionVariant>& p_v,
+                 const std::vector<std::shared_ptr<const IBoundaryConditionDescriptor>>& bc_descriptor_list) const
+  {
+    std::shared_ptr mesh_v = getCommonMesh({rho_v, aL_v, aT_v, u_v, sigma_v, p_v});
+    if (not mesh_v) {
+      throw NormalError("discrete functions are not defined on the same mesh");
+    }   //      - p* identity; // - chi_solid*P_zero_air_repo*identity;
+
+    if (not checkDiscretizationType({rho_v, aL_v, u_v, sigma_v, p_v}, DiscreteFunctionType::P0)) {
+      throw NormalError("hyperelastic solver expects P0 functions");
+    }
+
+    const MeshType& mesh                = *mesh_v->get<MeshType>();
+    const DiscreteScalarFunction& rho   = rho_v->get<DiscreteScalarFunction>();
+    const DiscreteVectorFunction& u     = u_v->get<DiscreteVectorFunction>();
+    const DiscreteScalarFunction& aL    = aL_v->get<DiscreteScalarFunction>();
+    const DiscreteScalarFunction& aT    = aT_v->get<DiscreteScalarFunction>();
+    const DiscreteTensorFunction& sigma = sigma_v->get<DiscreteTensorFunction>();
+    const DiscreteScalarFunction& p     = p_v->get<DiscreteScalarFunction>();
+
+    const TinyMatrix<Dimension> I = identity;
+    const DiscreteTensorFunction& S     = sigma + p*I;
+    const std::shared_ptr<const DiscreteFunctionVariant>& S_v = std::make_shared<DiscreteFunctionVariant>(S);
+
     std::vector<std::shared_ptr<const IBoundaryDescriptor>> symmetry_boundary_descriptor_list;
 
     for (auto&& bc_descriptor : bc_descriptor_list) {
@@ -719,102 +950,40 @@ class Order2HyperelasticSolverHandler::Order2HyperelasticSolver final
     PolynomialReconstructionDescriptor reconstruction_descriptor(IntegrationMethodType::cell_center, 1,
                                                                  symmetry_boundary_descriptor_list);
 
-    // CellValue<double> limiter_j{mesh.connectivity()};
-    // parallel_for(
-    //   mesh.numberOfCells(), PUGS_LAMBDA(CellId j){
-    //     limiter_j[j] = 1;
-    //   }
-    //);
-    //
-    // const CellValue<const Rdxd>& sigma_j = copy(sigma.cellValues());
-    // std::vector<DiscreteFunctionDPk<Dimension, double>> sigma_coef;
-    // std::vector<size_t> row;
-    // std::vector<size_t> col;
-    // for(size_t i = 0; i < Dimension; ++i){
-    //     for(size_t k = i; k < Dimension; ++k){
-    //
-    //         CellValue<double> coef{mesh.connectivity()};
-    //         for(CellId j = 0; j <mesh.numberOfCells(); ++j){
-    //             coef[j] = sigma_j[j](i,k);
-    //         }
-    //
-    //         const auto& coef_scalar_function = DiscreteScalarFunction(mesh_v, coef);
-    //         auto coef_v = std::make_shared<DiscreteFunctionVariant>(coef_scalar_function);
-    //         auto reconstruction = PolynomialReconstruction{reconstruction_descriptor}.build(coef_v);
-    //         auto DPk_coef = reconstruction[0]->get<DiscreteFunctionDPk<Dimension, const double>>();
-    //
-    //         const CellValue<const double>& limiter_ik =
-    //         _scalar_limiter_coefficient(mesh,coef_scalar_function,DPk_coef); parallel_for(
-    //           mesh.numberOfCells(), PUGS_LAMBDA(CellId j) {
-    //             limiter_j[j] = std::min(limiter_j[j],limiter_ik[j]);
-    //         });
-    //
-    //         sigma_coef.push_back(copy(DPk_coef));
-    //         row.push_back(i);
-    //         col.push_back(k);
-    //     }
-    // }
-    //
-    // NodeValuePerCell<Rdxd> sigma_lim{mesh.connectivity()} ;
-    // const auto& cell_to_node_matrix = mesh.connectivity().cellToNodeMatrix();
-    //
-    // parallel_for(
-    //   mesh.numberOfCells(), PUGS_LAMBDA(CellId j){
-    //     const auto& cell_nodes = cell_to_node_matrix[j];
-    //     for(size_t i = 0; i < Dimension; ++i){
-    //       for(size_t k = 0; k < Dimension; ++k){
-    //         for(size_t R = 0; R < cell_nodes.size(); ++R){
-    //           sigma_lim(j,R)(i,k) = 0;
-    //         }
-    //       }
-    //     }
-    //   }
-    //);
-    //
-    // const NodeValue<const Rd>& xr = copy(mesh.xr());
-    // parallel_for(
-    //     mesh.numberOfCells(), PUGS_LAMBDA(CellId j) {
-    //         const auto& cell_nodes = cell_to_node_matrix[j];
-    //
-    //         for(size_t R = 0; R < cell_nodes.size(); ++R){
-    //             const NodeId r = cell_nodes[R];
-    //
-    //             for(size_t l = 0; l < sigma_coef.size(); ++l){
-    //                 const size_t& i = row[l];
-    //                 const size_t& k = col[l];
-    //
-    //                 auto coefficients = sigma_coef[l].coefficients(j);
-    //
-    //                 coefficients[0] = (1-limiter_j[j])*sigma_j[j](i,k) + limiter_j[j] * coefficients[0];
-    //                 for (size_t indice = 1; indice < coefficients.size(); ++indice) {
-    //                   coefficients[indice] *= limiter_j[j];
-    //                 }
-    //
-    //                 sigma_lim(j,R)(i,k) = sigma_coef[l][j](xr[r]);
-    //                 if(i != k){
-    //                   sigma_lim(j,R)(i,k) *= 2;
-    //                 }
-    //             }
-    //
-    //             sigma_lim(j,R) += transpose(sigma_lim(j,R));
-    //             sigma_lim(j,R) *= 0.5;
-    //         }
-    //
-    //     }
-    //);
-    auto reconstruction = PolynomialReconstruction{reconstruction_descriptor}.build(u_v, sigma_v);
-    auto DPk_uh         = reconstruction[0]->get<DiscreteFunctionDPk<Dimension, const Rd>>();
-    auto DPk_sigmah     = reconstruction[1]->get<DiscreteFunctionDPk<Dimension, const Rdxd>>();
+    auto reconstruction = PolynomialReconstruction{reconstruction_descriptor}.build(u_v, S_v, p_v);
+    auto DPk_uh     = reconstruction[0]->get<DiscreteFunctionDPk<Dimension, const Rd>>();
+    auto DPk_Sh     = reconstruction[1]->get<DiscreteFunctionDPk<Dimension, const Rdxd>>();
+    auto DPk_ph     = reconstruction[2]->get<DiscreteFunctionDPk<Dimension, const double>>();
 
     DiscreteFunctionDPk<Dimension, Rd> u_lim       = copy(DPk_uh);
-    DiscreteFunctionDPk<Dimension, Rdxd> sigma_lim = copy(DPk_sigmah);
-    this->_vector_limiter(mesh, u, u_lim);
-    this->_tensor_limiter(mesh, sigma, sigma_lim);
+    DiscreteFunctionDPk<Dimension, Rdxd> S_lim     = copy(DPk_Sh);
+    DiscreteFunctionDPk<Dimension, double> p_lim   = copy(DPk_ph);
+
+    this->_vector_limiter(mesh, u, u_lim, DPk_ph);
+    CellValue<double> lambda = this->_matrix_limiter(mesh, S, S_lim);
+    this->_scalar_limiter(mesh, p, p_lim);
+
+    const NodeValue<const Rd>& xr        = mesh.xr();
+    const DiscreteScalarFunction& J2 = 0.5*trace(transpose(S)*S);
+    NodeValuePerCell<double> coef{mesh.connectivity()};
+    const auto& cell_to_node_matrix = mesh.connectivity().cellToNodeMatrix();
+    parallel_for(
+      mesh.numberOfCells(), PUGS_LAMBDA(CellId j){
+        const auto& cell_nodes = cell_to_node_matrix[j];
+        for(size_t r = 0; r < cell_nodes.size(); ++r){
+          const double J2_p = 0.5*trace(transpose(DPk_Sh[j](xr[cell_nodes[r]]))*DPk_Sh[j](xr[cell_nodes[r]]));
+          if(J2_p != 0.){
+            coef(j,r) = J2[j]/J2_p;
+          }else{
+          coef(j,r) = 0;
+          }
+        }
+    });
 
     NodeValuePerCell<const Rdxd> Ajr = this->_computeAjr(solver_type, mesh, rho * aL, rho * aT);
 
     NodeValue<Rdxd> Ar = this->_computeAr(mesh, Ajr);
-    NodeValue<Rd> br = this->_computeBr(mesh, Ajr, u_lim, sigma_lim);
+    NodeValue<Rd> br = this->_computeBr(mesh, Ajr, u_lim, S_lim, p_lim, lambda, coef);
 
     const BoundaryConditionList bc_list = this->_getBCList(mesh, bc_descriptor_list);
     this->_applyBoundaryConditions(bc_list, mesh, Ar, br);
@@ -823,7 +992,7 @@ class Order2HyperelasticSolverHandler::Order2HyperelasticSolver final
     synchronize(br);
 
     NodeValue<const Rd> ur = this->_computeUr(mesh, Ar, br);
-    NodeValuePerCell<const Rd> Fjr = this->_computeFjr(mesh, Ajr, ur, u_lim, sigma_lim);
+    NodeValuePerCell<const Rd> Fjr = this->_computeFjr(mesh, Ajr, ur, u_lim, S_lim, p_lim, lambda, coef);
 
     return std::make_tuple(std::make_shared<const ItemValueVariant>(ur),
                            std::make_shared<const SubItemValuePerItemVariant>(Fjr));
@@ -840,21 +1009,24 @@ class Order2HyperelasticSolverHandler::Order2HyperelasticSolver final
                const DiscreteVectorFunction& u,
                const DiscreteScalarFunction& E,
                const DiscreteTensorFunction& CG,
-               const NodeValue<const Rd>& ur,
-               const NodeValuePerCell<const Rd>& Fjr) const
+               const NodeValue<const Rd>& ur_o2,
+               const NodeValue<const Rd>& ur_o1,
+               const NodeValuePerCell<const Rd>& Fjr_o2,
+               const NodeValuePerCell<const Rd>& Fjr_o1) const
   {
     const auto& cell_to_node_matrix = mesh.connectivity().cellToNodeMatrix();
 
+    NodeValue<Rd> ur         = copy(ur_o2);
+    NodeValuePerCell<Rd> Fjr = copy(Fjr_o2);
+
     if ((mesh.shared_connectivity() != ur.connectivity_ptr()) or
         (mesh.shared_connectivity() != Fjr.connectivity_ptr())) {
       throw NormalError("fluxes are not defined on the same connectivity than the mesh");
     }
 
-    NodeValue<Rd> new_xr = copy(mesh.xr());
-    parallel_for(
-      mesh.numberOfNodes(), PUGS_LAMBDA(NodeId r) { new_xr[r] += dt * ur[r]; });
-
-    std::shared_ptr<const MeshType> new_mesh = std::make_shared<MeshType>(mesh.shared_connectivity(), new_xr);
+    StencilManager::BoundaryDescriptorList symmetry_boundary_descriptor_list;
+    StencilDescriptor stencil_descriptor{1, StencilDescriptor::ConnectionType::by_nodes};
+    auto stencil = StencilManager::instance().getCellToCellStencilArray(mesh.connectivity(), stencil_descriptor, symmetry_boundary_descriptor_list);
 
     CellValue<const double> Vj           = MeshDataManager::instance().getMeshData(mesh).Vj();
     const NodeValuePerCell<const Rd> Cjr = MeshDataManager::instance().getMeshData(mesh).Cjr();
@@ -864,29 +1036,105 @@ class Order2HyperelasticSolverHandler::Order2HyperelasticSolver final
     CellValue<double> new_E   = copy(E.cellValues());
     CellValue<Rdxd> new_CG    = copy(CG.cellValues());
 
+    CellValue<double> new_rho_stencil = copy(rho.cellValues());
+    CellValue<Rd> new_u_stencil       = copy(u.cellValues());
+    CellValue<double> new_E_stencil   = copy(E.cellValues());
+    CellValue<Rdxd> new_CG_stencil    = copy(CG.cellValues());
+
+    CellValue<int> cell_flag{mesh.connectivity()};
+
     parallel_for(
       mesh.numberOfCells(), PUGS_LAMBDA(CellId j) {
-        const auto& cell_nodes = cell_to_node_matrix[j];
+        auto cell_nodes = cell_to_node_matrix[j];
 
         Rd momentum_fluxes   = zero;
         double energy_fluxes = 0;
         Rdxd gradv           = zero;
         for (size_t R = 0; R < cell_nodes.size(); ++R) {
-          const NodeId r = cell_nodes[R];
+          NodeId r = cell_nodes[R];
           gradv += tensorProduct(ur[r], Cjr(j, R));
           momentum_fluxes += Fjr(j, R);
           energy_fluxes += dot(Fjr(j, R), ur[r]);
         }
-        const Rdxd cauchy_green_fluxes = gradv * CG[j] + CG[j] * transpose(gradv);
-        const double dt_over_Mj        = dt / (rho[j] * Vj[j]);
-        const double dt_over_Vj        = dt / Vj[j];
+        Rdxd cauchy_green_fluxes = gradv * CG[j] + CG[j] * transpose(gradv);
+        double dt_over_Mj        = dt / (rho[j] * Vj[j]);
+        double dt_over_Vj        = dt / Vj[j];
         new_u[j] += dt_over_Mj * momentum_fluxes;
         new_E[j] += dt_over_Mj * energy_fluxes;
         new_CG[j] += dt_over_Vj * cauchy_green_fluxes;
         new_CG[j] += transpose(new_CG[j]);
         new_CG[j] *= 0.5;
+
+        double new_eps = new_E[j] - 0.5 * dot(new_u[j],new_u[j]);
+        if(new_eps < 0.){
+          cell_flag[j] = 1;
+        }else{
+          cell_flag[j] = 0;
+        }
       });
 
+    for(CellId j = 0; j < mesh.numberOfCells(); ++j){
+      if(cell_flag[j] == 1){
+        const auto& cell_nodes = cell_to_node_matrix[j];
+
+        Rd momentum_fluxes   = zero;
+        double energy_fluxes = 0;
+        Rdxd gradv           = zero;
+        std::vector<NodeId> NodeList;
+        for (size_t R = 0; R < cell_nodes.size(); ++R) {
+          NodeId r = cell_nodes[R];
+          NodeList.push_back(r);
+          Fjr(j,R) = Fjr_o1(j,R);
+          ur[r] = ur_o1[r];
+          gradv += tensorProduct(ur[r], Cjr(j, R));
+          momentum_fluxes += Fjr(j, R);
+          energy_fluxes += dot(Fjr(j, R), ur[r]);
+        }
+        Rdxd cauchy_green_fluxes = gradv * CG[j] + CG[j] * transpose(gradv);
+        double dt_over_Mj        = dt / (rho[j] * Vj[j]);
+        double dt_over_Vj        = dt / Vj[j];
+        new_u[j] = new_u_stencil[j] +  dt_over_Mj * momentum_fluxes;
+        new_E[j] = new_E_stencil[j] + dt_over_Mj * energy_fluxes;
+        new_CG[j] = new_CG_stencil[j] + dt_over_Vj * cauchy_green_fluxes;
+        new_CG[j] += transpose(new_CG[j]);
+        new_CG[j] *= 0.5;
+
+        auto cell_stencil = stencil[j];
+        for(size_t i_cell = 0; i_cell < cell_stencil.size(); ++i_cell){
+          CellId J = cell_stencil[i_cell];
+          auto i_cell_nodes = cell_to_node_matrix[J];
+          momentum_fluxes = zero;
+          energy_fluxes   = 0;
+          gradv           = zero;
+          for (size_t R = 0; R < i_cell_nodes.size(); ++R) {
+            NodeId i_node = i_cell_nodes[R];
+            for(size_t node_test = 0; node_test < NodeList.size(); ++node_test){
+              if(NodeList[node_test] == i_node){
+                Fjr(J,R) = Fjr_o1(J,R);
+              }
+            }
+            gradv += tensorProduct(ur[i_node], Cjr(J, R));
+            momentum_fluxes += Fjr(J, R);
+            energy_fluxes += dot(Fjr(J, R), ur[i_node]);
+          }
+          cauchy_green_fluxes = gradv * CG[J] + CG[J] * transpose(gradv);
+          dt_over_Mj          = dt / (rho[J] * Vj[J]);
+          dt_over_Vj          = dt / Vj[J];
+          new_u[J] = new_u_stencil[J] +  dt_over_Mj * momentum_fluxes;
+          new_E[J] = new_E_stencil[J] + dt_over_Mj * energy_fluxes;
+          new_CG[J] = new_CG_stencil[J] + dt_over_Vj * cauchy_green_fluxes;
+          new_CG[J] += transpose(new_CG[J]);
+          new_CG[J] *= 0.5;
+        } 
+      }
+    }
+
+    NodeValue<Rd> new_xr = copy(mesh.xr());
+    parallel_for(
+      mesh.numberOfNodes(), PUGS_LAMBDA(NodeId r) { new_xr[r] += dt * ur[r]; });
+
+    std::shared_ptr<const MeshType> new_mesh = std::make_shared<MeshType>(mesh.shared_connectivity(), new_xr);
+
     CellValue<const double> new_Vj = MeshDataManager::instance().getMeshData(*new_mesh).Vj();
 
     parallel_for(
@@ -910,7 +1158,9 @@ class Order2HyperelasticSolverHandler::Order2HyperelasticSolver final
                const std::shared_ptr<const DiscreteFunctionVariant>& E,
                const std::shared_ptr<const DiscreteFunctionVariant>& CG,
                const std::shared_ptr<const ItemValueVariant>& ur,
-               const std::shared_ptr<const SubItemValuePerItemVariant>& Fjr) const
+               const std::shared_ptr<const ItemValueVariant>& ur_o1,
+               const std::shared_ptr<const SubItemValuePerItemVariant> Fjr,
+               const std::shared_ptr<const SubItemValuePerItemVariant> Fjr_o1) const
   {
     std::shared_ptr mesh_v = getCommonMesh({rho, u, E});
     if (not mesh_v) {
@@ -927,8 +1177,11 @@ class Order2HyperelasticSolverHandler::Order2HyperelasticSolver final
                               u->get<DiscreteVectorFunction>(),     //
                               E->get<DiscreteScalarFunction>(),     //
                               CG->get<DiscreteTensorFunction>(),    //
-                              ur->get<NodeValue<const Rd>>(),       //
-                              Fjr->get<NodeValuePerCell<const Rd>>());
+                              ur->get<NodeValue<const Rd>>(),
+                              ur_o1->get<NodeValue<const Rd>>(),       //
+                              Fjr->get<NodeValuePerCell<const Rd>>(),
+                              Fjr_o1->get<NodeValuePerCell<const Rd>>()
+                              );
   }
 
   std::tuple<std::shared_ptr<const MeshVariant>,
@@ -944,21 +1197,24 @@ class Order2HyperelasticSolverHandler::Order2HyperelasticSolver final
                       const DiscreteTensorFunction& CG,
                       const DiscreteScalarFunction& rho_app,
                       const DiscreteTensorFunction& CG_app,
-                      const NodeValue<const Rd>& ur,
-                      const NodeValuePerCell<const Rd>& Fjr) const
+                      const NodeValue<const Rd>& ur_o2,
+                      const NodeValue<const Rd>& ur_o1,
+                      const NodeValuePerCell<const Rd>& Fjr_o2,
+                      const NodeValuePerCell<const Rd>& Fjr_o1) const
   {
     const auto& cell_to_node_matrix = mesh.connectivity().cellToNodeMatrix();
 
+    NodeValue<Rd> ur         = copy(ur_o2);
+    NodeValuePerCell<Rd> Fjr = copy(Fjr_o2);
+
     if ((mesh.shared_connectivity() != ur.connectivity_ptr()) or
         (mesh.shared_connectivity() != Fjr.connectivity_ptr())) {
       throw NormalError("fluxes are not defined on the same connectivity than the mesh");
     }
 
-    NodeValue<Rd> new_xr = copy(mesh.xr());
-    parallel_for(
-      mesh.numberOfNodes(), PUGS_LAMBDA(NodeId r) { new_xr[r] += dt * ur[r]; });
-
-    std::shared_ptr<const MeshType> new_mesh = std::make_shared<MeshType>(mesh.shared_connectivity(), new_xr);
+    StencilManager::BoundaryDescriptorList symmetry_boundary_descriptor_list;
+    StencilDescriptor stencil_descriptor{1, StencilDescriptor::ConnectionType::by_nodes};
+    auto stencil = StencilManager::instance().getCellToCellStencilArray(mesh.connectivity(), stencil_descriptor, symmetry_boundary_descriptor_list);
 
     CellValue<const double> Vj           = MeshDataManager::instance().getMeshData(mesh).Vj();
     const NodeValuePerCell<const Rd> Cjr = MeshDataManager::instance().getMeshData(mesh).Cjr();
@@ -968,6 +1224,13 @@ class Order2HyperelasticSolverHandler::Order2HyperelasticSolver final
     CellValue<double> new_E   = copy(E.cellValues());
     CellValue<Rdxd> new_CG    = copy(CG.cellValues());
 
+    CellValue<double> new_rho_stencil = copy(rho.cellValues());
+    CellValue<Rd> new_u_stencil       = copy(u.cellValues());
+    CellValue<double> new_E_stencil   = copy(E.cellValues());
+    CellValue<Rdxd> new_CG_stencil    = copy(CG.cellValues());
+
+    CellValue<int> cell_flag{mesh.connectivity()};
+
     parallel_for(
       mesh.numberOfCells(), PUGS_LAMBDA(CellId j) {
         const auto& cell_nodes = cell_to_node_matrix[j];
@@ -988,8 +1251,75 @@ class Order2HyperelasticSolverHandler::Order2HyperelasticSolver final
         new_CG[j] += dt_over_Mj * cauchy_green_fluxes;
         new_CG[j] += transpose(new_CG[j]);
         new_CG[j] *= 0.5;
+
+        const double& new_eps = new_E[j] - 0.5 * dot(new_u[j],new_u[j]);
+        if(new_eps < 0.){
+          cell_flag[j] = 1;
+        }else{
+          cell_flag[j] = 0;
+        }
       });
 
+    for(CellId j = 0; j < mesh.numberOfCells(); ++j){
+      if(cell_flag[j] == 1){
+        const auto& cell_nodes = cell_to_node_matrix[j];
+
+        Rd momentum_fluxes   = zero;
+        double energy_fluxes = 0;
+        Rdxd gradv           = zero;
+        std::vector<NodeId> NodeList;
+        for (size_t R = 0; R < cell_nodes.size(); ++R) {
+          NodeId r = cell_nodes[R];
+          NodeList.push_back(r);
+          Fjr(j,R) = Fjr_o1(j,R);
+          ur[r] = ur_o1[r];
+          gradv += tensorProduct(ur[r], Cjr(j, R));
+          momentum_fluxes += Fjr(j, R);
+          energy_fluxes += dot(Fjr(j, R), ur[r]);
+        }
+        Rdxd cauchy_green_fluxes = rho_app[j] * (gradv * CG_app[j] + CG_app[j] * transpose(gradv));
+        double dt_over_Mj        = dt / (rho[j] * Vj[j]);
+        new_u[j] = new_u_stencil[j] + dt_over_Mj * momentum_fluxes;
+        new_E[j] = new_E_stencil[j] + dt_over_Mj * energy_fluxes;
+        new_CG[j] = new_CG_stencil[j] + dt_over_Mj * cauchy_green_fluxes;
+        new_CG[j] += transpose(new_CG[j]);
+        new_CG[j] *= 0.5;
+
+        auto cell_stencil = stencil[j];
+        for(size_t i_cell = 0; i_cell < cell_stencil.size(); ++i_cell){
+          CellId J = cell_stencil[i_cell];
+          auto i_cell_nodes = cell_to_node_matrix[J];
+          momentum_fluxes = zero;
+          energy_fluxes   = 0;
+          gradv           = zero;
+          for (size_t R = 0; R < i_cell_nodes.size(); ++R) {
+            NodeId i_node = i_cell_nodes[R];
+            for(size_t node_test = 0; node_test < NodeList.size(); ++node_test){
+              if(NodeList[node_test] == i_node){
+                Fjr(J,R) = Fjr_o1(J,R);
+              }
+            }
+            gradv += tensorProduct(ur[i_node], Cjr(J, R));
+            momentum_fluxes += Fjr(J, R);
+            energy_fluxes += dot(Fjr(J, R), ur[i_node]);
+          }
+          cauchy_green_fluxes = rho_app[J] * (gradv * CG_app[J] + CG_app[J] * transpose(gradv));
+          dt_over_Mj        = dt / (rho[J] * Vj[J]);
+          new_u[J] = new_u_stencil[J] + dt_over_Mj * momentum_fluxes;
+          new_E[J] = new_E_stencil[J] + dt_over_Mj * energy_fluxes;
+          new_CG[J] = new_CG_stencil[J] + dt_over_Mj * cauchy_green_fluxes;
+          new_CG[J] += transpose(new_CG[J]);
+          new_CG[J] *= 0.5;
+        } 
+      }
+    }
+
+    NodeValue<Rd> new_xr = copy(mesh.xr());
+    parallel_for(
+      mesh.numberOfNodes(), PUGS_LAMBDA(NodeId r) { new_xr[r] += dt * ur[r]; });
+
+    std::shared_ptr<const MeshType> new_mesh = std::make_shared<MeshType>(mesh.shared_connectivity(), new_xr);
+
     CellValue<const double> new_Vj = MeshDataManager::instance().getMeshData(*new_mesh).Vj();
 
     parallel_for(
@@ -1015,7 +1345,9 @@ class Order2HyperelasticSolverHandler::Order2HyperelasticSolver final
                       const std::shared_ptr<const DiscreteFunctionVariant>& rho_app,
                       const std::shared_ptr<const DiscreteFunctionVariant>& CG_app,
                       const std::shared_ptr<const ItemValueVariant>& ur,
-                      const std::shared_ptr<const SubItemValuePerItemVariant>& Fjr) const
+                      const std::shared_ptr<const ItemValueVariant>& ur_o1,
+                      const std::shared_ptr<const SubItemValuePerItemVariant>& Fjr,
+                      const std::shared_ptr<const SubItemValuePerItemVariant>& Fjr_o1) const
   {
     std::shared_ptr mesh_v = getCommonMesh({rho, u, E});
     if (not mesh_v) {
@@ -1035,7 +1367,9 @@ class Order2HyperelasticSolverHandler::Order2HyperelasticSolver final
                                      rho_app->get<DiscreteScalarFunction>(),   //
                                      CG_app->get<DiscreteTensorFunction>(),    //
                                      ur->get<NodeValue<const Rd>>(),           //
-                                     Fjr->get<NodeValuePerCell<const Rd>>());
+                                     ur_o1->get<NodeValue<const Rd>>(),
+                                     Fjr->get<NodeValuePerCell<const Rd>>(),
+                                     Fjr_o1->get<NodeValuePerCell<const Rd>>());
   }
 
   std::tuple<std::shared_ptr<const MeshVariant>,
@@ -1053,6 +1387,7 @@ class Order2HyperelasticSolverHandler::Order2HyperelasticSolver final
         const std::shared_ptr<const DiscreteFunctionVariant>& aL,
         const std::shared_ptr<const DiscreteFunctionVariant>& aT,
         const std::shared_ptr<const DiscreteFunctionVariant>& sigma,
+        const std::shared_ptr<const DiscreteFunctionVariant>& p,
         const std::vector<std::shared_ptr<const IBoundaryConditionDescriptor>>& bc_descriptor_list,
         const std::shared_ptr<const DiscreteFunctionVariant>& chi_solid,
         const double& lambda,
@@ -1062,22 +1397,26 @@ class Order2HyperelasticSolverHandler::Order2HyperelasticSolver final
         const double& gamma_s,
         const double& p_inf_s) const
   {
-    std::shared_ptr m_app                                  = getCommonMesh({rho, aL, aT, u, sigma});
-    std::shared_ptr<const DiscreteFunctionVariant> rho_app = rho;
-    std::shared_ptr<const DiscreteFunctionVariant> u_app   = u;
-    std::shared_ptr<const DiscreteFunctionVariant> E_app   = E;
-    std::shared_ptr<const DiscreteFunctionVariant> CG_app  = CG;
+    //std::shared_ptr m_app                                  = getCommonMesh({rho, aL, aT, u, sigma});
+    //std::shared_ptr<const DiscreteFunctionVariant> rho_app = rho;
+    //std::shared_ptr<const DiscreteFunctionVariant> u_app   = u;
+    //std::shared_ptr<const DiscreteFunctionVariant> E_app   = E;
+    //std::shared_ptr<const DiscreteFunctionVariant> CG_app  = CG;
+
+    auto [ur, Fjr]       = compute_fluxes(solver_type, rho, aL, aT, u, sigma, p, bc_descriptor_list);
+    auto [ur_o1, Fjr_o1] = compute_fluxes(solver_type, rho, aL, aT, u, sigma, bc_descriptor_list);
 
-    auto [ur, Fjr] = compute_fluxes(solver_type, rho, aL, aT, u, sigma, bc_descriptor_list);
-    // auto [m_app, rho_app, u_app, E_app, CG_app] = apply_fluxes(dt/2., rho, u, E, CG, ur, Fjr);
+    auto [m_app, rho_app, u_app, E_app, CG_app] = apply_fluxes(dt/2., rho, u, E, CG, ur, ur_o1, Fjr, Fjr_o1);
 
-    // std::shared_ptr<const DiscreteFunctionVariant> chi_solid_app = shallowCopy(m_app, chi_solid);
+    std::shared_ptr<const DiscreteFunctionVariant> chi_solid_app = shallowCopy(m_app, chi_solid);
 
-    // auto [sigma_app, aL_app, aT_app] =
-    // _apply_state_law(law,rho_app,u_app,E_app,CG_app,chi_solid_app,lambda,mu,gamma_f,p_inf_f,gamma_s,p_inf_s);
+    auto [sigma_app, p_app, aL_app, aT_app] =
+    _apply_state_law(law,rho_app,u_app,E_app,CG_app,chi_solid_app,lambda,mu,gamma_f,p_inf_f,gamma_s,p_inf_s);
 
-    // auto [ur_app, Fjr_app] = compute_fluxes(solver_type, rho_app, aL_app,aT_app,u_app,sigma_app,bc_descriptor_list);
-    return apply_fluxes(dt, rho, u, E, CG, ur, Fjr);
+    auto [ur_app, Fjr_app] = compute_fluxes(solver_type, rho_app, aL_app,aT_app,u_app,sigma_app, p_app, bc_descriptor_list);
+    auto [ur_o1_app, Fjr_o1_app] = compute_fluxes(solver_type, rho_app, aL_app,aT_app,u_app,sigma_app,bc_descriptor_list);
+    return order2_apply_fluxes(dt, rho, u, E, CG, rho_app, CG_app, ur_app, ur_o1_app, Fjr_app, Fjr_o1_app);
+    //return apply_fluxes(dt, rho, u, E, CG, ur, ur_o1, Fjr, Fjr_o1);
   }
 
   Order2HyperelasticSolver()                           = default;
diff --git a/src/scheme/Order2HyperelasticSolver.hpp b/src/scheme/Order2HyperelasticSolver.hpp
index 0051bd0d7966323dae9d69a03ac9d4b2193478b5..99f9616045268e9775be368a34b7a2f3ca81e14b 100644
--- a/src/scheme/Order2HyperelasticSolver.hpp
+++ b/src/scheme/Order2HyperelasticSolver.hpp
@@ -25,30 +25,6 @@ class Order2HyperelasticSolverHandler
  private:
   struct IOrder2HyperelasticSolver
   {
-    virtual std::tuple<const std::shared_ptr<const ItemValueVariant>,
-                       const std::shared_ptr<const SubItemValuePerItemVariant>>
-    compute_fluxes(
-      const SolverType& solver_type,
-      const std::shared_ptr<const DiscreteFunctionVariant>& rho,
-      const std::shared_ptr<const DiscreteFunctionVariant>& aL,
-      const std::shared_ptr<const DiscreteFunctionVariant>& aT,
-      const std::shared_ptr<const DiscreteFunctionVariant>& u,
-      const std::shared_ptr<const DiscreteFunctionVariant>& sigma,
-      const std::vector<std::shared_ptr<const IBoundaryConditionDescriptor>>& bc_descriptor_list) const = 0;
-
-    virtual std::tuple<std::shared_ptr<const MeshVariant>,
-                       std::shared_ptr<const DiscreteFunctionVariant>,
-                       std::shared_ptr<const DiscreteFunctionVariant>,
-                       std::shared_ptr<const DiscreteFunctionVariant>,
-                       std::shared_ptr<const DiscreteFunctionVariant>>
-    apply_fluxes(const double& dt,
-                 const std::shared_ptr<const DiscreteFunctionVariant>& rho,
-                 const std::shared_ptr<const DiscreteFunctionVariant>& u,
-                 const std::shared_ptr<const DiscreteFunctionVariant>& E,
-                 const std::shared_ptr<const DiscreteFunctionVariant>& CG,
-                 const std::shared_ptr<const ItemValueVariant>& ur,
-                 const std::shared_ptr<const SubItemValuePerItemVariant>& Fjr) const = 0;
-
     virtual std::tuple<std::shared_ptr<const MeshVariant>,
                        std::shared_ptr<const DiscreteFunctionVariant>,
                        std::shared_ptr<const DiscreteFunctionVariant>,
@@ -64,6 +40,7 @@ class Order2HyperelasticSolverHandler
           const std::shared_ptr<const DiscreteFunctionVariant>& aL,
           const std::shared_ptr<const DiscreteFunctionVariant>& aT,
           const std::shared_ptr<const DiscreteFunctionVariant>& sigma,
+          const std::shared_ptr<const DiscreteFunctionVariant>& p,
           const std::vector<std::shared_ptr<const IBoundaryConditionDescriptor>>& bc_descriptor_list,
           const std::shared_ptr<const DiscreteFunctionVariant>& chi_solid,
           const double& lambda,