diff --git a/src/language/modules/SchemeModule.cpp b/src/language/modules/SchemeModule.cpp
index dc9502f90106ee888d7d5b5f0ae7ca687b2aab66..ca49d0b16565877fc526dc9c5f7a8740975582d4 100644
--- a/src/language/modules/SchemeModule.cpp
+++ b/src/language/modules/SchemeModule.cpp
@@ -604,16 +604,17 @@ SchemeModule::SchemeModule()
 
       ));
   this->_addBuiltinFunction("nodalheat",
-                            std::make_shared<BuiltinFunctionEmbedder<std::shared_ptr<
-                              const IDiscreteFunction>(const std::shared_ptr<const IDiscreteFunction>&,
-                                                       const std::shared_ptr<const IDiscreteFunction>&,
-                                                       const std::shared_ptr<const IDiscreteFunction>&,
-                                                       const std::vector<
-                                                         std::shared_ptr<const IBoundaryConditionDescriptor>>&,
-                                                       const std::vector<
-                                                         std::shared_ptr<const IBoundaryConditionDescriptor>>&,
-                                                       const std::shared_ptr<const IDiscreteFunction>&, const double&,
-                                                       const double&)>>(
+                            std::make_shared<BuiltinFunctionEmbedder<std::tuple<
+                              std::shared_ptr<const IDiscreteFunction>,
+                              std::shared_ptr<const IDiscreteFunction>>(const std::shared_ptr<const IDiscreteFunction>&,
+                                                                        const std::shared_ptr<const IDiscreteFunction>&,
+                                                                        const std::shared_ptr<const IDiscreteFunction>&,
+                                                                        const std::vector<std::shared_ptr<
+                                                                          const IBoundaryConditionDescriptor>>&,
+                                                                        const std::vector<std::shared_ptr<
+                                                                          const IBoundaryConditionDescriptor>>&,
+                                                                        const std::shared_ptr<const IDiscreteFunction>&,
+                                                                        const double&, const double&)>>(
 
                               [](const std::shared_ptr<const IDiscreteFunction>& kappa,
                                  const std::shared_ptr<const IDiscreteFunction>& f,
@@ -623,7 +624,8 @@ SchemeModule::SchemeModule()
                                  const std::vector<std::shared_ptr<const IBoundaryConditionDescriptor>>&
                                    bc_prev_descriptor_list,
                                  const std::shared_ptr<const IDiscreteFunction>& P, const double& dt,
-                                 const double& cn_coeff) -> const std::shared_ptr<const IDiscreteFunction> {
+                                 const double& cn_coeff) -> const std::tuple<std::shared_ptr<const IDiscreteFunction>,
+                                                                             std::shared_ptr<const IDiscreteFunction>> {
                                 return ScalarNodalSchemeHandler{kappa,
                                                                 f,
                                                                 f_prev,
@@ -633,9 +635,7 @@ SchemeModule::SchemeModule()
                                                                 dt,
                                                                 cn_coeff}
                                   .solution();
-                              }
-
-                              ));
+                              }));
 
   this->_addBuiltinFunction("unsteadyelasticity",
                             std::make_shared<BuiltinFunctionEmbedder<
diff --git a/src/scheme/ScalarNodalScheme.cpp b/src/scheme/ScalarNodalScheme.cpp
index f380a0fff001b0b20aee1d39bf4d3382e53cbf51..6a827b0145f1ee309a8bc806f064487236fb11a3 100644
--- a/src/scheme/ScalarNodalScheme.cpp
+++ b/src/scheme/ScalarNodalScheme.cpp
@@ -6,7 +6,10 @@
 class ScalarNodalSchemeHandler::IScalarNodalScheme
 {
  public:
-  virtual std::shared_ptr<const IDiscreteFunction> getSolution() const = 0;
+  virtual std::tuple<std::shared_ptr<const IDiscreteFunction>, std::shared_ptr<const IDiscreteFunction>> getSolution()
+    const = 0;
+
+  // virtual std::shared_ptr<const IDiscreteFunction> getSolution() const = 0;
 
   IScalarNodalScheme()          = default;
   virtual ~IScalarNodalScheme() = default;
@@ -20,7 +23,9 @@ class ScalarNodalSchemeHandler::ScalarNodalScheme : public ScalarNodalSchemeHand
   using MeshType         = Mesh<ConnectivityType>;
   using MeshDataType     = MeshData<Dimension>;
 
-  std::shared_ptr<const DiscreteFunctionP0<Dimension, double>> m_solution;
+  std::shared_ptr<const DiscreteFunctionP0<Dimension, double>> m_cell_temperature;
+  std::shared_ptr<const DiscreteFunctionP0<Dimension, double>> m_node_temperature;
+  //  std::shared_ptr<const DiscreteFunctionP0<Dimension, double>> m_solution;
 
   class DirichletBoundaryCondition
   {
@@ -136,11 +141,16 @@ class ScalarNodalSchemeHandler::ScalarNodalScheme : public ScalarNodalSchemeHand
   };
 
  public:
-  std::shared_ptr<const IDiscreteFunction>
-  getSolution() const final
+  std::tuple<std::shared_ptr<const IDiscreteFunction>, std::shared_ptr<const IDiscreteFunction>>
+  getSolution() const
   {
-    return m_solution;
+    return {m_cell_temperature, m_node_temperature};
   }
+  // std::shared_ptr<const IDiscreteFunction>
+  // getSolution() const final
+  // {
+  //   return m_solution;
+  // }
 
   ScalarNodalScheme(const std::shared_ptr<const MeshType>& mesh,
                     const std::shared_ptr<const DiscreteFunctionP0<Dimension, TinyMatrix<Dimension>>>& cell_k,
@@ -303,6 +313,11 @@ class ScalarNodalSchemeHandler::ScalarNodalScheme : public ScalarNodalSchemeHand
 
     MeshDataType& mesh_data = MeshDataManager::instance().getMeshData(*mesh);
 
+    std::shared_ptr dual_mesh = DualMeshManager::instance().getMedianDualMesh(*mesh);
+
+    std::shared_ptr mapper =
+      DualConnectivityManager::instance().getPrimalToMedianDualConnectivityDataMapper(mesh->connectivity());
+
     const NodeValue<const TinyVector<Dimension>>& xr = mesh->xr();
 
     const FaceValue<const TinyVector<Dimension>>& xl = mesh_data.xl();
@@ -313,7 +328,7 @@ class ScalarNodalSchemeHandler::ScalarNodalScheme : public ScalarNodalSchemeHand
     const auto is_boundary_node = mesh->connectivity().isBoundaryNode();
     const auto is_boundary_face = mesh->connectivity().isBoundaryFace();
 
-    const auto& face_to_cell_matrix               = mesh->connectivity().faceToCellMatrix();
+    //    const auto& face_to_cell_matrix               = mesh->connectivity().faceToCellMatrix();
     const auto& node_to_face_matrix               = mesh->connectivity().nodeToFaceMatrix();
     const auto& face_to_node_matrix               = mesh->connectivity().faceToNodeMatrix();
     const auto& cell_to_node_matrix               = mesh->connectivity().cellToNodeMatrix();
@@ -737,7 +752,6 @@ class ScalarNodalSchemeHandler::ScalarNodalScheme : public ScalarNodalSchemeHand
       non_zeros.fill(4);   // Modif pour optimiser
       CRSMatrixDescriptor<double> S1(mesh->numberOfCells(), mesh->numberOfCells(), non_zeros);
       CRSMatrixDescriptor<double> S2(mesh->numberOfCells(), mesh->numberOfCells(), non_zeros);
-      CRSMatrixDescriptor<double> C(mesh->numberOfCells(), mesh->numberOfCells(), non_zeros);
 
       for (NodeId node_id = 0; node_id < mesh->numberOfNodes(); ++node_id) {
         const auto& node_to_cell = node_to_cell_matrix[node_id];
@@ -747,7 +761,6 @@ class ScalarNodalSchemeHandler::ScalarNodalScheme : public ScalarNodalSchemeHand
             const CellId cell_id_k   = node_to_cell[i_cell_k];
             S1(cell_id_j, cell_id_k) = 0;
             S2(cell_id_j, cell_id_k) = 0;
-            C(cell_id_j, cell_id_k)  = 0;
           }
         }
       }
@@ -835,32 +848,6 @@ class ScalarNodalSchemeHandler::ScalarNodalScheme : public ScalarNodalSchemeHand
         }
       }
 
-      for (FaceId face_id = 0; face_id < mesh->numberOfFaces(); ++face_id) {
-        if (not is_boundary_face[face_id]) {
-          const auto& face_to_cell = face_to_cell_matrix[face_id];
-          CellId cell_id_j         = face_to_cell[0];
-          CellId cell_id_k         = face_to_cell[1];
-          C(cell_id_j, cell_id_j) += dt * mes_l[face_id] / l2Norm(xj[cell_id_j] - xj[cell_id_k]);
-          C(cell_id_k, cell_id_k) += dt * mes_l[face_id] / l2Norm(xj[cell_id_j] - xj[cell_id_k]);
-          C(cell_id_j, cell_id_k) -= dt * mes_l[face_id] / l2Norm(xj[cell_id_j] - xj[cell_id_k]);
-          C(cell_id_k, cell_id_j) -= dt * mes_l[face_id] / l2Norm(xj[cell_id_j] - xj[cell_id_k]);
-        } else {
-          const auto& face_to_cell = face_to_cell_matrix[face_id];
-          CellId cell_id_j         = face_to_cell[0];
-          C(cell_id_j, cell_id_j) += dt * mes_l[face_id] / l2Norm(xj[cell_id_j] - xl[face_id]);
-        }
-      }
-
-      const double epsilon = 0.5;
-
-      for (CellId cell_id_j = 0; cell_id_j < mesh->numberOfCells(); ++cell_id_j) {
-        for (CellId cell_id_k = 0; cell_id_k < mesh->numberOfCells(); ++cell_id_k) {
-          if (S1(cell_id_j, cell_id_k) != 0 or C(cell_id_j, cell_id_k) != 0) {
-            S1(cell_id_j, cell_id_k) = (1. - epsilon) * S1(cell_id_j, cell_id_k) + epsilon * C(cell_id_j, cell_id_k);
-          }
-        }
-      }
-
       for (CellId cell_id = 0; cell_id < mesh->numberOfCells(); ++cell_id) {
         S1(cell_id, cell_id) += Vj[cell_id];
         S2(cell_id, cell_id) += Vj[cell_id];
@@ -1010,15 +997,51 @@ class ScalarNodalSchemeHandler::ScalarNodalScheme : public ScalarNodalSchemeHand
       LinearSolver solver;
       solver.solveLocalSystem(A1, T, B);
 
-      m_solution     = std::make_shared<DiscreteFunctionP0<Dimension, double>>(mesh);
-      auto& solution = *m_solution;
+      const NodeValue<const double> primal_node_temperature = [&] {
+        NodeValue<double> compute_primal_node_temperature{mesh->connectivity()};
+        compute_primal_node_temperature.fill(0);
+        parallel_for(
+          mesh->numberOfNodes(), PUGS_LAMBDA(NodeId node_id) {
+            // for (NodeId node_id = 0; node_id < mesh->numberOfNodes(); node_id++) {
+            const auto& node_to_cell = node_to_cell_matrix[node_id];
+            double sum_Vj            = 0;
+            for (size_t i_cell = 0; i_cell < node_to_cell.size(); ++i_cell) {
+              const CellId cell_id = node_to_cell[i_cell];
+              compute_primal_node_temperature[node_id] += Vj[cell_id] * T[cell_id];
+              sum_Vj += Vj[cell_id];
+            }
+            compute_primal_node_temperature[node_id] /= sum_Vj;
+          });
+        return compute_primal_node_temperature;
+      }();
+
+      const CellValue<const double> dual_node_temperature = [=] {
+        CellValue<double> my_dual_temperature{dual_mesh->connectivity()};
+        mapper->toDualCell(primal_node_temperature, my_dual_temperature);
+        return my_dual_temperature;
+      }();
+
+      // m_solution     = std::make_shared<DiscreteFunctionP0<Dimension, double>>(mesh);
+      m_cell_temperature = std::make_shared<DiscreteFunctionP0<Dimension, double>>(mesh);
+      m_node_temperature = std::make_shared<DiscreteFunctionP0<Dimension, double>>(dual_mesh);
+      // auto& solution = *m_solution;
+      auto& cell_temperature = *m_cell_temperature;
+      auto& node_temperature = *m_node_temperature;
+      parallel_for(
+        mesh->numberOfCells(), PUGS_LAMBDA(CellId cell_id) { cell_temperature[cell_id] = T[cell_id]; });
       parallel_for(
-        mesh->numberOfCells(), PUGS_LAMBDA(CellId cell_id) { solution[cell_id] = T[cell_id]; });
+        dual_mesh->numberOfCells(),
+        PUGS_LAMBDA(CellId cell_id) { node_temperature[cell_id] = dual_node_temperature[cell_id]; });
     }
   }
 };
 
-std::shared_ptr<const IDiscreteFunction>
+// std::shared_ptr<const IDiscreteFunction>
+// ScalarNodalSchemeHandler::solution() const
+// {
+//   return m_scheme->getSolution();
+// }
+std::tuple<std::shared_ptr<const IDiscreteFunction>, std::shared_ptr<const IDiscreteFunction>>
 ScalarNodalSchemeHandler::solution() const
 {
   return m_scheme->getSolution();
diff --git a/src/scheme/ScalarNodalScheme.hpp b/src/scheme/ScalarNodalScheme.hpp
index 930b15d2513a6edf8061bf9884cfc2eac1d69982..f5a0b3f7c8f2a16d4fa2a774684ec9298d1a9a8b 100644
--- a/src/scheme/ScalarNodalScheme.hpp
+++ b/src/scheme/ScalarNodalScheme.hpp
@@ -17,6 +17,7 @@
 #include <mesh/MeshFaceBoundary.hpp>
 #include <mesh/MeshNodeBoundary.hpp>
 #include <mesh/PrimalToDiamondDualConnectivityDataMapper.hpp>
+#include <mesh/PrimalToMedianDualConnectivityDataMapper.hpp>
 #include <mesh/SubItemValuePerItem.hpp>
 #include <scheme/DirichletBoundaryConditionDescriptor.hpp>
 #include <scheme/FourierBoundaryConditionDescriptor.hpp>
@@ -38,7 +39,8 @@ class ScalarNodalSchemeHandler
  public:
   std::unique_ptr<IScalarNodalScheme> m_scheme;
 
-  std::shared_ptr<const IDiscreteFunction> solution() const;
+  // std::shared_ptr<const IDiscreteFunction> solution() const;
+  std::tuple<std::shared_ptr<const IDiscreteFunction>, std::shared_ptr<const IDiscreteFunction>> solution() const;
 
   ScalarNodalSchemeHandler(
     const std::shared_ptr<const IDiscreteFunction>& cell_k,