diff --git a/src/scheme/HyperelasticSolver.cpp b/src/scheme/HyperelasticSolver.cpp
index 3a9725d107d801f58c915a090b0ccc840f4bbde8..c18ca1e54be07e11b8b94f1a03efb6da6b58af37 100644
--- a/src/scheme/HyperelasticSolver.cpp
+++ b/src/scheme/HyperelasticSolver.cpp
@@ -7,6 +7,7 @@
 #include <mesh/MeshFlatNodeBoundary.hpp>
 #include <mesh/MeshNodeBoundary.hpp>
 #include <mesh/SubItemValuePerItemVariant.hpp>
+#include <scheme/CouplingBoundaryConditionDescriptor.hpp>
 #include <scheme/DirichletBoundaryConditionDescriptor.hpp>
 #include <scheme/DiscreteFunctionP0.hpp>
 #include <scheme/DiscreteFunctionUtils.hpp>
@@ -81,6 +82,7 @@ class HyperelasticSolverHandler::HyperelasticSolver final : public HyperelasticS
 #endif   // PUGS_HAS_COSTO
   class SymmetryBoundaryCondition;
   class VelocityBoundaryCondition;
+  class CouplingBoundaryCondition;
 
   using BoundaryCondition = std::variant<FixedBoundaryCondition,
                                          PressureBoundaryCondition,
@@ -88,6 +90,7 @@ class HyperelasticSolverHandler::HyperelasticSolver final : public HyperelasticS
 #ifdef PUGS_HAS_COSTO
                                          CplDirichletBoundaryCondition,
 #endif   // PUGS_HAS_COSTO
+                                         CouplingBoundaryCondition,
                                          SymmetryBoundaryCondition,
                                          VelocityBoundaryCondition>;
 
@@ -390,6 +393,12 @@ class HyperelasticSolverHandler::HyperelasticSolver final : public HyperelasticS
         }
         break;
       }
+      case IBoundaryConditionDescriptor::Type::coupling: {
+        const CouplingBoundaryConditionDescriptor& coupling_bc_descriptor =
+          dynamic_cast<const CouplingBoundaryConditionDescriptor&>(*bc_descriptor);
+        bc_list.emplace_back(CouplingBoundaryCondition(getMeshNodeBoundary(mesh, bc_descriptor->boundaryDescriptor())));
+        break;
+      }
       default: {
         is_valid_boundary_condition = false;
       }
@@ -411,6 +420,7 @@ class HyperelasticSolverHandler::HyperelasticSolver final : public HyperelasticS
 #endif   // PUGS_HAS_COSTO
   void _applySymmetryBC(const BoundaryConditionList& bc_list, NodeValue<Rdxd>& Ar, NodeValue<Rd>& br) const;
   void _applyVelocityBC(const BoundaryConditionList& bc_list, NodeValue<Rdxd>& Ar, NodeValue<Rd>& br) const;
+  void _applyCouplingBC(const BoundaryConditionList& bc_list, NodeValue<Rdxd>& Ar, NodeValue<Rd>& br) const;
   void
   _applyBoundaryConditions(const BoundaryConditionList& bc_list,
                            const MeshType& mesh,
@@ -495,6 +505,7 @@ class HyperelasticSolverHandler::HyperelasticSolver final : public HyperelasticS
 
     const BoundaryConditionList bc_list = this->_getBCList(mesh, bc_descriptor_list);
     this->_applyBoundaryConditions(bc_list, mesh, Ar, br);
+    this->_applyCouplingBC(bc_list, Ar, br);
 
     synchronize(Ar);
     synchronize(br);
@@ -854,6 +865,87 @@ HyperelasticSolverHandler::HyperelasticSolver<Dimension>::_applyVelocityBC(const
   }
 }
 
+template <size_t Dimension>
+void
+HyperelasticSolverHandler::HyperelasticSolver<Dimension>::_applyCouplingBC(const BoundaryConditionList& bc_list,
+                                                                           NodeValue<Rdxd>& Ar,
+                                                                           NodeValue<Rd>& br) const
+{
+  for (const auto& boundary_condition : bc_list) {
+    std::visit(
+      [&](auto&& bc) {
+        using T = std::decay_t<decltype(bc)>;
+        if constexpr (std::is_same_v<CouplingBoundaryCondition, T>) {
+          const auto& node_list = bc.nodeList();
+
+        /* std::cout << "\033[01;31m" */
+        /*           << "un applyCoupling" */
+        /*           << "Dimension: " << Dimension << "\033[00;00m" << std::endl; */
+        /* std::cout << "\033[01;31m" */
+        /*           << "node_list.size()" << node_list.size() << "\033[00;00m" << std::endl; */
+
+#ifdef PUGS_HAS_COSTO
+          auto costo     = parallel::Messenger::getInstance().myCoupling;
+          const int dest = costo->myGlobalSize() - 1;
+          int tag        = 200;
+          std::vector<int> shape;
+          shape.resize(3);
+          shape[0] = node_list.size();
+          shape[1] = Dimension + Dimension * Dimension;
+          /* shape[1] = Dimension; */
+          shape[2] = 0;
+
+          std::vector<double> data;
+          data.resize(shape[0] * shape[1] + shape[2]);
+          Array<TinyVector<Dimension>> br_extracted(node_list.size());
+          Array<TinyMatrix<Dimension>> Ar_extracted(node_list.size());
+          parallel_for(
+            node_list.size(), PUGS_LAMBDA(size_t i_node) {
+              NodeId node_id = node_list[i_node];
+              for (size_t i_dim = 0; i_dim < Dimension; i_dim++) {
+                br_extracted[i_node] = br[node_id];
+                Ar_extracted[i_node] = Ar[node_id];
+              }
+            });
+          /*TODO: serializer directement Ar et br pour eviter une copie*/
+          for (size_t i_node = 0; i_node < node_list.size(); ++i_node) {
+            for (unsigned short i_dim = 0; i_dim < Dimension; ++i_dim) {
+              data[i_node * shape[1] + i_dim] = br_extracted[i_node][i_dim];
+              for (size_t j_dim = 0; j_dim < Dimension; j_dim++) {
+                data[i_node * shape[1] + Dimension + i_dim * Dimension + j_dim] = Ar_extracted[i_node](i_dim, j_dim);
+              }
+            }
+          }
+          costo->sendData(shape, data, dest, tag);
+          std::vector<double> recv;
+
+          tag = 210;
+          costo->recvData(recv, dest, tag);
+          for (size_t i_node = 0; i_node < node_list.size(); ++i_node) {
+            for (unsigned short i_dim = 0; i_dim < Dimension; ++i_dim) {
+              br_extracted[i_node][i_dim] = recv[i_node * shape[1] + i_dim];
+              for (size_t j_dim = 0; j_dim < Dimension; j_dim++) {
+                Ar_extracted[i_node](i_dim, j_dim) = recv[i_node * shape[1] + Dimension + i_dim * Dimension + j_dim];
+              }
+            }
+          }
+
+          parallel_for(
+            node_list.size(), PUGS_LAMBDA(size_t i_node) {
+              NodeId node_id = node_list[i_node];
+              for (size_t i_dim = 0; i_dim < Dimension; i_dim++) {
+                br[node_id] = br_extracted[i_node];
+                Ar[node_id] = Ar_extracted[i_node];
+              }
+            });
+
+#endif PUGS_HAS_COSTO
+        }
+      },
+      boundary_condition);
+  }
+}
+
 template <size_t Dimension>
 class HyperelasticSolverHandler::HyperelasticSolver<Dimension>::FixedBoundaryCondition
 {
@@ -1080,6 +1172,28 @@ class HyperelasticSolverHandler::HyperelasticSolver<Dimension>::SymmetryBoundary
   ~SymmetryBoundaryCondition() = default;
 };
 
+template <size_t Dimension>
+class HyperelasticSolverHandler::HyperelasticSolver<Dimension>::CouplingBoundaryCondition
+{
+ private:
+  const MeshNodeBoundary<Dimension> m_mesh_node_boundary;
+
+ public:
+  const Array<const NodeId>&
+  nodeList() const
+  {
+    return m_mesh_node_boundary.nodeList();
+  }
+
+  CouplingBoundaryCondition(const MeshNodeBoundary<Dimension>& mesh_node_boundary)
+    : m_mesh_node_boundary{mesh_node_boundary}
+  {
+    ;
+  }
+
+  ~CouplingBoundaryCondition() = default;
+};
+
 HyperelasticSolverHandler::HyperelasticSolverHandler(const std::shared_ptr<const IMesh>& i_mesh)
 {
   if (not i_mesh) {
diff --git a/src/scheme/HyperelasticSolver.hpp b/src/scheme/HyperelasticSolver.hpp
index f82cbe361051efc64a3e413d60c830febd62d907..044ccd96f80fff4a46613b32346b19b46af23ed1 100644
--- a/src/scheme/HyperelasticSolver.hpp
+++ b/src/scheme/HyperelasticSolver.hpp
@@ -1,6 +1,4 @@
-#ifndef HYPERELASTIC_SOLVER_HPP
-#define HYPERELASTIC_SOLVER_HPP
-
+#pragma once
 #include <memory>
 #include <tuple>
 #include <vector>
@@ -86,5 +84,3 @@ class HyperelasticSolverHandler
 
   HyperelasticSolverHandler(const std::shared_ptr<const IMesh>& mesh);
 };
-
-#endif   // HYPERELASTIC_SOLVER_HPP