diff --git a/src/scheme/ImplicitAcousticSolver.cpp b/src/scheme/ImplicitAcousticSolver.cpp
index 2b74689bf36b506d094ea05198707139a4007f3d..7cfed87083e24a82ecdac253669fd58fa1bf382e 100644
--- a/src/scheme/ImplicitAcousticSolver.cpp
+++ b/src/scheme/ImplicitAcousticSolver.cpp
@@ -106,6 +106,7 @@ class ImplicitAcousticSolverHandler::ImplicitAcousticSolver final
   CellValue<const double> m_g_1_exp_S_Cv_inv_g;
   CellValue<const double> m_tau_iter;
 
+  CellValue<const Rd> m_u;
   CellValue<const double> m_tau;
   CellValue<const double> m_Mj;
 
@@ -358,15 +359,15 @@ class ImplicitAcousticSolverHandler::ImplicitAcousticSolver final
     auto is_boundary_node = m_mesh.connectivity().isBoundaryNode();
 
     non_zeros.fill(0);
-    for (CellId cell_id = 0; cell_id < m_mesh.numberOfCells(); ++cell_id) {
-      if (m_is_implicit_cell[cell_id]) {
-        const auto& cell_node = cell_to_node_matrix[cell_id];
+    for (CellId cell_j_id = 0; cell_j_id < m_mesh.numberOfCells(); ++cell_j_id) {
+      if (m_is_implicit_cell[cell_j_id]) {
+        const auto& cell_j_nodes = cell_to_node_matrix[cell_j_id];
         std::vector<size_t> nb_neighbors;
         nb_neighbors.reserve(30);
 
-        for (size_t id_node = 0; id_node < cell_node.size(); ++id_node) {
-          if (not is_boundary_node[cell_node[id_node]]) {
-            NodeId node_id        = cell_node[id_node];
+        for (size_t id_node = 0; id_node < cell_j_nodes.size(); ++id_node) {
+          if (not is_boundary_node[cell_j_nodes[id_node]]) {
+            NodeId node_id        = cell_j_nodes[id_node];
             const auto& node_cell = node_to_cell_matrix[node_id];
             for (size_t cell_i = 0; cell_i < node_cell.size(); ++cell_i) {
               CellId id_cell_i = node_cell[cell_i];
@@ -380,11 +381,11 @@ class ImplicitAcousticSolverHandler::ImplicitAcousticSolver final
         auto last = std::unique(nb_neighbors.begin(), nb_neighbors.end());
         nb_neighbors.resize(std::distance(nb_neighbors.begin(), last));
 
-        size_t line_index_p     = mapP(cell_id);
+        size_t line_index_p     = mapP(cell_j_id);
         non_zeros[line_index_p] = Dimension * nb_neighbors.size() + 1;
 
         for (size_t i_dimension = 0; i_dimension < Dimension; ++i_dimension) {
-          size_t line_index_u     = mapU(i_dimension, cell_id);
+          size_t line_index_u     = mapU(i_dimension, cell_j_id);
           non_zeros[line_index_u] = nb_neighbors.size() + 1;
         }
 
@@ -400,21 +401,22 @@ class ImplicitAcousticSolverHandler::ImplicitAcousticSolver final
         const auto& node_cell                      = node_to_cell_matrix[node_id];
         const auto& node_local_number_in_its_cells = node_local_numbers_in_their_cells.itemArray(node_id);
 
-        for (size_t i_dimension = 0; i_dimension < Dimension; ++i_dimension) {
-          for (size_t cell_i = 0; cell_i < node_cell.size(); ++cell_i) {
-            const CellId id_cell_i = node_cell[cell_i];
-            if (m_is_implicit_cell[id_cell_i]) {
-              const size_t node_nb_in_i = node_local_number_in_its_cells[cell_i];
-              const int i_index_u       = mapU(i_dimension, id_cell_i);
-              for (size_t cell_j = 0; cell_j < node_cell.size(); ++cell_j) {
-                const CellId id_cell_j = node_cell[cell_j];
-                if (m_is_implicit_cell[id_cell_j]) {
-                  const size_t node_nb_in_j = node_local_number_in_its_cells[cell_j];
-                  const int j_index_p       = mapP(id_cell_j);
-
-                  const Rd coef = m_Ajr(id_cell_i, node_nb_in_i) * m_inv_Ar[node_id] * m_Djr(id_cell_j, node_nb_in_j);
-                  A(j_index_p, i_index_u) += coef[i_dimension];
-                  A(i_index_u, j_index_p) -= coef[i_dimension];
+        for (size_t cell_i = 0; cell_i < node_cell.size(); ++cell_i) {
+          const CellId id_cell_i = node_cell[cell_i];
+          if (m_is_implicit_cell[id_cell_i]) {
+            const size_t node_nb_in_i = node_local_number_in_its_cells[cell_i];
+            for (size_t cell_j = 0; cell_j < node_cell.size(); ++cell_j) {
+              const CellId id_cell_j = node_cell[cell_j];
+              if (m_is_implicit_cell[id_cell_j]) {
+                const size_t node_nb_in_j = node_local_number_in_its_cells[cell_j];
+                const int j_index_p       = mapP(id_cell_j);
+
+                const Rd Bji = m_Ajr(id_cell_i, node_nb_in_i) * m_inv_Ar[node_id] * m_Djr(id_cell_j, node_nb_in_j);
+                for (size_t i_dimension = 0; i_dimension < Dimension; ++i_dimension) {
+                  const int i_index_u = mapU(i_dimension, id_cell_i);
+
+                  A(j_index_p, i_index_u) += Bji[i_dimension];
+                  A(i_index_u, j_index_p) -= Bji[i_dimension];
                 }
               }
             }
@@ -584,7 +586,7 @@ class ImplicitAcousticSolverHandler::ImplicitAcousticSolver final
         m_mesh.numberOfCells(), PUGS_LAMBDA(CellId j) {
           if (m_is_implicit_cell[j]) {
             size_t k             = mapP(j);
-            computed_tau_iter[j] = m_g_1_exp_S_Cv_inv_g[j] * pow(-Uk[k] + pi[j], -m_inv_gamma[j]);
+            computed_tau_iter[j] = m_g_1_exp_S_Cv_inv_g[j] * std::pow(-Uk[k] + pi[j], -m_inv_gamma[j]);
           }
         });
       return computed_tau_iter;
@@ -899,6 +901,80 @@ class ImplicitAcousticSolverHandler::ImplicitAcousticSolver final
     return F;
   }
 
+  Vector<double>
+  _getF_new(const CRSMatrix<double, int>& A,
+            const Vector<double>& Un,
+            const Vector<double>& Uk,
+            const DiscreteScalarFunction& p,
+            const DiscreteScalarFunction& pi,
+            const DiscreteVectorFunction& u,
+            const double dt)
+  {
+    const auto& cell_to_node_matrix = m_mesh.connectivity().cellToNodeMatrix();
+
+    NodeValue<const Rd> ur         = this->_getUr();
+    NodeValuePerCell<const Rd> Fjr = this->_getFjr(ur);
+
+    m_tau_iter = [&]() {
+      CellValue<double> computed_tau_iter(m_mesh.connectivity());
+      parallel_for(
+        m_mesh.numberOfCells(), PUGS_LAMBDA(CellId j) {
+          if (m_is_implicit_cell[j]) {
+            size_t k             = mapP(j);
+            computed_tau_iter[j] = m_g_1_exp_S_Cv_inv_g[j] * std::pow(-Uk[k] + pi[j], -m_inv_gamma[j]);
+          }
+        });
+      return computed_tau_iter;
+    }();
+
+    CellValue<double> volume_fluxes_sum{m_mesh.connectivity()};
+    parallel_for(
+      m_mesh.numberOfCells(), PUGS_LAMBDA(const CellId cell_id) {
+        double sum             = 0;
+        const auto& cell_nodes = cell_to_node_matrix[cell_id];
+        for (size_t i_node = 0; i_node < cell_nodes.size(); ++i_node) {
+          const NodeId node_id = cell_nodes[i_node];
+          sum += dot(m_Djr(cell_id, i_node), ur[node_id]);
+        }
+        volume_fluxes_sum[cell_id] = sum;
+      });
+
+    CellValue<Rd> momentum_fluxes_sum{m_mesh.connectivity()};
+    parallel_for(
+      m_mesh.numberOfCells(), PUGS_LAMBDA(const CellId cell_id) {
+        Rd sum                 = zero;
+        const auto& cell_nodes = cell_to_node_matrix[cell_id];
+        for (size_t i_node = 0; i_node < cell_nodes.size(); ++i_node) {
+          sum += Fjr(cell_id, i_node);
+        }
+        momentum_fluxes_sum[cell_id] = sum;
+      });
+
+    Vector<double> F{Un.size()};
+    F.fill(0);
+
+    parallel_for(
+      m_mesh.numberOfCells(), PUGS_LAMBDA(const CellId cell_id) {
+        if (m_is_implicit_cell[cell_id]) {
+          const size_t pj_index = mapP(cell_id);
+          F[pj_index] =
+            m_Mj[cell_id] / dt *
+              (m_g_1_exp_S_Cv_inv_g[cell_id] * std::pow(-Uk[pj_index] + pi[cell_id], -m_inv_gamma[cell_id]) -
+               m_tau[cell_id]) -
+            volume_fluxes_sum[cell_id];
+
+          for (size_t i_dimension = 0; i_dimension < Dimension; ++i_dimension) {
+            const size_t uj_i_index = mapU(i_dimension, cell_id);
+
+            F[uj_i_index] =
+              m_Mj[cell_id] / dt * (Uk[uj_i_index] - Un[uj_i_index]) + momentum_fluxes_sum[cell_id][i_dimension];
+          }
+        }
+      });
+
+    return F;
+  }
+
   CRSMatrixDescriptor<double>
   _getHessianJ(const double dt, const DiscreteScalarFunction& pi, const Vector<double>& Uk)
   {
@@ -948,9 +1024,6 @@ class ImplicitAcousticSolverHandler::ImplicitAcousticSolver final
                                (Dimension + 1) * m_number_of_implicit_cells, non_zeros};
 
     const auto& node_local_numbers_in_their_cells = m_mesh.connectivity().nodeLocalNumbersInTheirCells();
-    MeshDataType& mesh_data                       = MeshDataManager::instance().getMeshData(m_mesh);
-
-    const NodeValuePerCell<const Rd>& Cjr = mesh_data.Cjr();
 
     count_getGradF++;
     static bool getGradF_is_started = false;
@@ -986,14 +1059,14 @@ class ImplicitAcousticSolverHandler::ImplicitAcousticSolver final
             const size_t node_nb_in_j_cell = node_local_number_in_its_cells[j_cell];
             const int j_index_p            = mapP(cell_id_j);
 
-            const auto invArCir = inv_Ar * Cjr(cell_id_j, node_nb_in_j_cell);
+            const auto invArDjr = inv_Ar * m_Djr(cell_id_j, node_nb_in_j_cell);
 
             for (size_t i_cell = 0; i_cell < node_cell.size(); ++i_cell) {
               const CellId cell_id_i = node_cell[i_cell];
               if (m_is_implicit_cell[cell_id_i]) {
                 const size_t node_nb_in_cell_i = node_local_number_in_its_cells[i_cell];
                 const int i_index_p            = mapP(cell_id_i);
-                Hess_J(j_index_p, i_index_p) += dot(invArCir, Cjr(cell_id_i, node_nb_in_cell_i));
+                Hess_J(j_index_p, i_index_p) += dot(invArDjr, m_Djr(cell_id_i, node_nb_in_cell_i));
               }
             }
           }
@@ -1142,7 +1215,7 @@ class ImplicitAcousticSolverHandler::ImplicitAcousticSolver final
                         const size_t node_nb_in_j = node_local_number_in_its_cells[cell_j];
                         const int j_index_p       = mapP(id_cell_j);
                         Hess_J(i_index_p, j_index_p) +=
-                          dot(Cjr(id_cell_i, node_nb_in_i), inverse_ArxP[node_id] * Cjr(id_cell_j, node_nb_in_j));
+                          dot(m_Djr(id_cell_i, node_nb_in_i), inverse_ArxP[node_id] * m_Djr(id_cell_j, node_nb_in_j));
                       }
                     }
                   }
@@ -1203,7 +1276,7 @@ class ImplicitAcousticSolverHandler::ImplicitAcousticSolver final
             //             const int j_index_p       = mapP(id_cell_j);
 
             //             Hess_J(i_index_p, j_index_p) +=
-            //               dot(Cjr(id_cell_i, node_nb_in_i), m_inv_Ar[node_id] * Cjr(id_cell_j, node_nb_in_j));
+            //               dot(m_Djr(id_cell_i, node_nb_in_i), m_inv_Ar[node_id] * m_Djr(id_cell_j, node_nb_in_j));
             //           }
             //         }
             //       }
@@ -1428,7 +1501,8 @@ class ImplicitAcousticSolverHandler::ImplicitAcousticSolver final
     if (m_number_of_implicit_cells > 0) {
       do {
         nb_iter++;
-        Vector<double> f = this->_getF(A, Un, Uk, p, pi, u, dt);
+        // Vector<double> f_old     = this->_getF(A, Un, Uk, p, pi, u, dt);
+        Vector<double> f = this->_getF_new(A, Un, Uk, p, pi, u, dt);
 
         std::cout << "building gradf: ";
         CRSMatrix<double> gradient_f = this->_getGradientF(A, Uk, pi, dt);
@@ -1466,7 +1540,7 @@ class ImplicitAcousticSolverHandler::ImplicitAcousticSolver final
 
         std::cout << rang::style::bold << "norm resid = " << l2Norm(f - gradient_f * sol) << rang::style::reset << '\n';
         // std::exit(0);
-        Vector<double> U_next = Uk - sol;
+        Vector<double> U_next = Uk - 0.2 * sol;
 
         Array<const double> abs_sol = [&]() {
           Array<double> compute_abs_sol{sol.size()};
@@ -1477,24 +1551,24 @@ class ImplicitAcousticSolverHandler::ImplicitAcousticSolver final
 
         norm_inf_sol = max(abs_sol);
 
-        Uk = U_next;
-
         std::cout << "nb_iter= " << nb_iter << " | ratio Newton = " << norm_inf_sol / norm_inf_Un << "\n";
 
         // when it is a hard case we relax newton
         size_t neg_pressure_count = 0;
         double min_pressure       = 0;
-        for (CellId j = 0; j < m_number_of_implicit_cells; ++j) {
-          size_t k = mapP(j);
-          if (-U_next[k] + pi[j] < 0) {
+        for (CellId cell_id = 0; cell_id < m_number_of_implicit_cells; ++cell_id) {
+          size_t k = mapP(cell_id);
+          if (-U_next[k] + pi[cell_id] < 0) {
+            std::cout << " neg p: cell_id=" << cell_id << '\n';
             ++neg_pressure_count;
-            min_pressure = std::min(min_pressure, -U_next[k] + pi[j]);
-            U_next[k]    = Uk[k] + sol[k];
+            min_pressure = std::min(min_pressure, -U_next[k] + pi[cell_id]);
+            U_next[k]    = Uk[k];
           }
         }
         if (neg_pressure_count > 0) {
           std::cout << rang::fgB::magenta << "p est negatif sur " << neg_pressure_count
                     << " mailles min=" << min_pressure << rang::fg::reset << '\n';
+          std::exit(0);
         }
         // Uk -= sol;
         // if (neg_pressure) {
@@ -1504,33 +1578,36 @@ class ImplicitAcousticSolverHandler::ImplicitAcousticSolver final
         //   Uk -= sol;
         // }
 
-      } while ((norm_inf_sol > 1e-15 * norm_inf_Un) and (nb_iter < 200));
-    }
-    m_predicted_u = [&] {
-      CellValue<Rd> predicted_u = copy(u.cellValues());
-      for (CellId cell_id = 0; cell_id < m_mesh.numberOfCells(); ++cell_id) {
-        if (m_is_implicit_cell[cell_id]) {
-          Rd vector_u = zero;
-          for (size_t i_dimension = 0; i_dimension < Dimension; ++i_dimension) {
-            vector_u[i_dimension] = Uk[mapU(i_dimension, cell_id)];
+        Uk = U_next;
+
+        m_predicted_u = [&] {
+          CellValue<Rd> predicted_u = copy(u.cellValues());
+          for (CellId cell_id = 0; cell_id < m_mesh.numberOfCells(); ++cell_id) {
+            if (m_is_implicit_cell[cell_id]) {
+              Rd vector_u = zero;
+              for (size_t i_dimension = 0; i_dimension < Dimension; ++i_dimension) {
+                vector_u[i_dimension] = Uk[mapU(i_dimension, cell_id)];
+              }
+              predicted_u[cell_id] = vector_u;
+            }
+            // std::cout << "u[" << cell_id << "]=" << predicted_u[cell_id] << '\n';
           }
-          predicted_u[cell_id] = vector_u;
-        }
-        // std::cout << "u[" << cell_id << "]=" << predicted_u[cell_id] << '\n';
-      }
-      return predicted_u;
-    }();
+          return predicted_u;
+        }();
 
-    m_predicted_p = [&] {
-      CellValue<double> predicted_p = copy(p.cellValues());
-      for (CellId cell_id = 0; cell_id < m_mesh.numberOfCells(); ++cell_id) {
-        if (m_is_implicit_cell[cell_id]) {
-          predicted_p[cell_id] = -Uk[mapP(cell_id)];
-        }
-        // std::cout << "p[" << cell_id << "]=" << predicted_p[cell_id] << '\n';
-      }
-      return predicted_p;
-    }();
+        m_predicted_p = [&] {
+          CellValue<double> predicted_p = copy(p.cellValues());
+          for (CellId cell_id = 0; cell_id < m_mesh.numberOfCells(); ++cell_id) {
+            if (m_is_implicit_cell[cell_id]) {
+              predicted_p[cell_id] = -Uk[mapP(cell_id)];
+            }
+            // std::cout << "p[" << cell_id << "]=" << predicted_p[cell_id] << '\n';
+          }
+          return predicted_p;
+        }();
+
+      } while ((norm_inf_sol > 1e-15 * norm_inf_Un) or (nb_iter < 100));
+    }
 
     for (CellId j = 0; j < m_mesh.numberOfCells(); ++j) {
       // faudrait mettre p+pi
@@ -1538,11 +1615,138 @@ class ImplicitAcousticSolverHandler::ImplicitAcousticSolver final
         std::cout << "pression negative pour la maille" << j << '\n';
       }
     }
+  }
+
+  NodeValue<const Rd>
+  _getUr() const
+  {
+    const auto& node_to_cell_matrix               = m_mesh.connectivity().nodeToCellMatrix();
+    const auto& node_local_numbers_in_their_cells = m_mesh.connectivity().nodeLocalNumbersInTheirCells();
+
+    NodeValue<Rd> b{m_mesh.connectivity()};
+
+    parallel_for(
+      m_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 += m_Ajr(J, R) * m_predicted_u[J] + m_predicted_p[J] * m_Djr(J, R);
+        }
+
+        b[r] = br;
+      });
+
+    for (const auto& boundary_condition : m_boundary_condition_list) {
+      std::visit(
+        [&](auto&& bc) {
+          using T = std::decay_t<decltype(bc)>;
+          if constexpr (std::is_same_v<PressureBoundaryCondition, T>) {
+            MeshData<Dimension>& mesh_data = MeshDataManager::instance().getMeshData(m_mesh);
+            if constexpr (Dimension == 1) {
+              const NodeValuePerCell<const Rd> Cjr = mesh_data.Cjr();
+
+              const auto& node_to_cell_matrix               = m_mesh.connectivity().nodeToCellMatrix();
+              const auto& node_local_numbers_in_their_cells = m_mesh.connectivity().nodeLocalNumbersInTheirCells();
+
+              const auto& node_list  = bc.faceList();
+              const auto& value_list = bc.valueList();
+              parallel_for(
+                node_list.size(), PUGS_LAMBDA(size_t i_node) {
+                  const NodeId node_id       = node_list[i_node];
+                  const auto& node_cell_list = node_to_cell_matrix[node_id];
+                  Assert(node_cell_list.size() == 1);
+
+                  CellId node_cell_id              = node_cell_list[0];
+                  size_t node_local_number_in_cell = node_local_numbers_in_their_cells(node_id, 0);
+
+                  b[node_id] -= value_list[i_node] * Cjr(node_cell_id, node_local_number_in_cell);
+                });
+            } else {
+              const NodeValuePerFace<const Rd> Nlr = mesh_data.Nlr();
+
+              const auto& face_to_cell_matrix               = m_mesh.connectivity().faceToCellMatrix();
+              const auto& face_to_node_matrix               = m_mesh.connectivity().faceToNodeMatrix();
+              const auto& face_local_numbers_in_their_cells = m_mesh.connectivity().faceLocalNumbersInTheirCells();
+              const auto& face_cell_is_reversed             = m_mesh.connectivity().cellFaceIsReversed();
+
+              const auto& face_list  = bc.faceList();
+              const auto& value_list = bc.valueList();
+              for (size_t i_face = 0; i_face < face_list.size(); ++i_face) {
+                const FaceId face_id       = face_list[i_face];
+                const auto& face_cell_list = face_to_cell_matrix[face_id];
+                Assert(face_cell_list.size() == 1);
+
+                CellId face_cell_id              = face_cell_list[0];
+                size_t face_local_number_in_cell = face_local_numbers_in_their_cells(face_id, 0);
+
+                const double sign = face_cell_is_reversed(face_cell_id, face_local_number_in_cell) ? -1 : 1;
+
+                const auto& face_nodes = face_to_node_matrix[face_id];
+
+                for (size_t i_node = 0; i_node < face_nodes.size(); ++i_node) {
+                  NodeId node_id = face_nodes[i_node];
+                  b[node_id] -= sign * value_list[i_face] * Nlr(face_id, i_node);
+                }
+              }
+            }
+          } else if constexpr (std::is_same_v<SymmetryBoundaryCondition, T>) {
+            // const auto cell_to_node_matrix = m_mesh.connectivity().cellToNodeMatrix();
+            auto is_boundary_node = m_mesh.connectivity().isBoundaryNode();
+
+            const Rd& n                          = bc.outgoingNormal();
+            const Rdxd I                         = identity;
+            const Rdxd nxn                       = tensorProduct(n, n);
+            const Rdxd P                         = I - nxn;
+            const Array<const NodeId>& node_list = bc.nodeList();
+            parallel_for(
+              bc.numberOfNodes(), PUGS_LAMBDA(int r_number) {
+                const NodeId r = node_list[r_number];
+                b[r]           = P * b[r];
+              });
+
+          } else if constexpr (std::is_same_v<VelocityBoundaryCondition, T>) {
+            const auto& node_list  = bc.nodeList();
+            const auto& value_list = bc.valueList();
+
+            parallel_for(
+              node_list.size(), PUGS_LAMBDA(size_t i_node) {
+                NodeId node_id    = node_list[i_node];
+                const auto& value = value_list[i_node];
+                b[node_id]        = value;
+              });
+          } else {
+            throw UnexpectedError("boundary condition not handled 5");
+          }
+        },
+        boundary_condition);
+    }
+
+    const NodeValue<Rd> computed_ur(m_mesh.connectivity());
+    parallel_for(
+      m_mesh.numberOfNodes(), PUGS_LAMBDA(NodeId r) { computed_ur[r] = m_inv_Ar[r] * b[r]; });
+
+    return computed_ur;
+  }
+
+  NodeValuePerCell<const Rd>
+  _getFjr(const NodeValue<const Rd>& ur) const
+  {
+    const auto& cell_to_node_matrix = m_mesh.connectivity().cellToNodeMatrix();
+    const NodeValuePerCell<Rd> computed_Fjr(m_mesh.connectivity());
+    parallel_for(
+      m_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) {
+          computed_Fjr(j, r) = m_Ajr(j, r) * (m_predicted_u[j] - ur[cell_nodes[r]]) + (m_predicted_p[j] * m_Djr(j, r));
+        }
+      });
 
-    // std::cout << "Uk=" << Uk << '\n';
-    // std::cout << "predicted_p" << m_predicted_p << '\n';
-    // std::cout << m_predicted_u << '\n';
-    // std::exit(0);
+    return computed_Fjr;
   }
 
   ImplicitAcousticSolver(const SolverType solver_type,
@@ -1647,6 +1851,11 @@ class ImplicitAcousticSolverHandler::ImplicitAcousticSolver final
       return computed_Mj;
     }();
 
+    m_u = u.cellValues();
+
+    m_predicted_u = m_u;
+    m_predicted_p = p.cellValues();
+
     m_tau = [&]() {
       CellValue<double> computed_tau(m_mesh.connectivity());
 
@@ -1673,7 +1882,7 @@ class ImplicitAcousticSolverHandler::ImplicitAcousticSolver final
       parallel_for(
         m_mesh.numberOfCells(), PUGS_LAMBDA(CellId j) {
           if (m_is_implicit_cell[j]) {
-            computed_g_1_exp_S_Cv_inv_g[j] = pow((gamma[j] - 1) * exp(entropy[j] / Cv[j]), m_inv_gamma[j]);
+            computed_g_1_exp_S_Cv_inv_g[j] = std::pow((gamma[j] - 1) * exp(entropy[j] / Cv[j]), m_inv_gamma[j]);
           }
         });
       return computed_g_1_exp_S_Cv_inv_g;
@@ -1687,149 +1896,10 @@ class ImplicitAcousticSolverHandler::ImplicitAcousticSolver final
       new_u   = copy(u.cellValues());
       new_E   = copy(E.cellValues());
 
-      _computeGradJU_AU(u, p, pi, dt);
-
-      // u_j+1/2
-      NodeValue<const Rd> ur = [&]() {
-        const auto& node_to_cell_matrix               = m_mesh.connectivity().nodeToCellMatrix();
-        const auto& node_local_numbers_in_their_cells = m_mesh.connectivity().nodeLocalNumbersInTheirCells();
-
-        NodeValue<Rd> b{m_mesh.connectivity()};
-
-        parallel_for(
-          m_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 += m_Ajr(J, R) * m_predicted_u[J] + m_predicted_p[J] * m_Djr(J, R);
-            }
-
-            b[r] = br;
-          });
-
-        for (const auto& boundary_condition : m_boundary_condition_list) {
-          std::visit(
-            [&](auto&& bc) {
-              using T = std::decay_t<decltype(bc)>;
-              if constexpr (std::is_same_v<PressureBoundaryCondition, T>) {
-                MeshData<Dimension>& mesh_data = MeshDataManager::instance().getMeshData(*mesh);
-                if constexpr (Dimension == 1) {
-                  const NodeValuePerCell<const Rd> Cjr = mesh_data.Cjr();
-
-                  const auto& node_to_cell_matrix               = m_mesh.connectivity().nodeToCellMatrix();
-                  const auto& node_local_numbers_in_their_cells = m_mesh.connectivity().nodeLocalNumbersInTheirCells();
-
-                  const auto& node_list  = bc.faceList();
-                  const auto& value_list = bc.valueList();
-                  parallel_for(
-                    node_list.size(), PUGS_LAMBDA(size_t i_node) {
-                      const NodeId node_id       = node_list[i_node];
-                      const auto& node_cell_list = node_to_cell_matrix[node_id];
-                      Assert(node_cell_list.size() == 1);
-
-                      CellId node_cell_id              = node_cell_list[0];
-                      size_t node_local_number_in_cell = node_local_numbers_in_their_cells(node_id, 0);
-
-                      b[node_id] -= value_list[i_node] * Cjr(node_cell_id, node_local_number_in_cell);
-                    });
-                } else {
-                  const NodeValuePerFace<const Rd> Nlr = mesh_data.Nlr();
-
-                  const auto& face_to_cell_matrix               = m_mesh.connectivity().faceToCellMatrix();
-                  const auto& face_to_node_matrix               = m_mesh.connectivity().faceToNodeMatrix();
-                  const auto& face_local_numbers_in_their_cells = m_mesh.connectivity().faceLocalNumbersInTheirCells();
-                  const auto& face_cell_is_reversed             = m_mesh.connectivity().cellFaceIsReversed();
-
-                  const auto& face_list  = bc.faceList();
-                  const auto& value_list = bc.valueList();
-                  for (size_t i_face = 0; i_face < face_list.size(); ++i_face) {
-                    const FaceId face_id       = face_list[i_face];
-                    const auto& face_cell_list = face_to_cell_matrix[face_id];
-                    Assert(face_cell_list.size() == 1);
-
-                    CellId face_cell_id              = face_cell_list[0];
-                    size_t face_local_number_in_cell = face_local_numbers_in_their_cells(face_id, 0);
-
-                    const double sign = face_cell_is_reversed(face_cell_id, face_local_number_in_cell) ? -1 : 1;
-
-                    const auto& face_nodes = face_to_node_matrix[face_id];
-
-                    for (size_t i_node = 0; i_node < face_nodes.size(); ++i_node) {
-                      NodeId node_id = face_nodes[i_node];
-                      b[node_id] -= sign * value_list[i_face] * Nlr(face_id, i_node);
-                    }
-                  }
-                }
-              } else if constexpr (std::is_same_v<SymmetryBoundaryCondition, T>) {
-                // const auto cell_to_node_matrix = m_mesh.connectivity().cellToNodeMatrix();
-                auto is_boundary_node = m_mesh.connectivity().isBoundaryNode();
-
-                const Rd& n                          = bc.outgoingNormal();
-                const Rdxd I                         = identity;
-                const Rdxd nxn                       = tensorProduct(n, n);
-                const Rdxd P                         = I - nxn;
-                const Array<const NodeId>& node_list = bc.nodeList();
-                parallel_for(
-                  bc.numberOfNodes(), PUGS_LAMBDA(int r_number) {
-                    const NodeId r = node_list[r_number];
-                    b[r]           = P * b[r];
-                  });
-
-              } else if constexpr (std::is_same_v<VelocityBoundaryCondition, T>) {
-                const auto& node_list  = bc.nodeList();
-                const auto& value_list = bc.valueList();
-
-                parallel_for(
-                  node_list.size(), PUGS_LAMBDA(size_t i_node) {
-                    NodeId node_id    = node_list[i_node];
-                    const auto& value = value_list[i_node];
-                    b[node_id]        = value;
-                  });
-              } else {
-                throw UnexpectedError("boundary condition not handled 5");
-              }
-            },
-            boundary_condition);
-        }
-
-        const NodeValue<Rd> computed_ur(m_mesh.connectivity());
-        parallel_for(
-          m_mesh.numberOfNodes(), PUGS_LAMBDA(NodeId r) { computed_ur[r] = m_inv_Ar[r] * b[r]; });
-
-        return computed_ur;
-      }();
-
-      // std::cout << "flux vitesse" << ur << '\n';
-      // std::exit(0);
-
-      //  p_j+1/2
-      const NodeValuePerCell<Rd>& Fjr = [&]() {
-        const auto& cell_to_node_matrix = m_mesh.connectivity().cellToNodeMatrix();
-        const NodeValuePerCell<Rd> computed_Fjr(m_mesh.connectivity());
-        parallel_for(
-          m_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) {
-              computed_Fjr(j, r) =
-                m_Ajr(j, r) * (m_predicted_u[j] - ur[cell_nodes[r]]) + (m_predicted_p[j] * m_Djr(j, r));
-            }
-          });
-
-        return computed_Fjr;
-      }();
+      this->_computeGradJU_AU(u, p, pi, dt);
 
-      // std::cout << "flux pression" << '\n';
-      // for (CellId cell_id = 0; cell_id < m_mesh.numberOfCells(); ++cell_id) {
-      //   const size_t& nb_nodes = m_Ajr.numberOfSubValues(cell_id);
-      //   for (size_t r = 0; r < nb_nodes; ++r) {
-      //     std::cout << "Fjr(" << cell_id << "," << r << ")=" << Fjr(cell_id, r) << '\n';
-      //   }
-      // }
+      NodeValue<const Rd> ur         = this->_getUr();
+      NodeValuePerCell<const Rd> Fjr = this->_getFjr(ur);
 
       // time n+1
       const auto& cell_to_node_matrix = m_mesh.connectivity().cellToNodeMatrix();