diff --git a/src/language/modules/CouplageModule.cpp b/src/language/modules/CouplageModule.cpp
index 0e3af73f020577979f5cd83c185e260cb1032864..cdb9e2194afb4ba944b08dda5dfd7c3a8309b844 100644
--- a/src/language/modules/CouplageModule.cpp
+++ b/src/language/modules/CouplageModule.cpp
@@ -11,6 +11,7 @@
 #include <mesh/Connectivity.hpp>
 #include <mesh/Mesh.hpp>
 #include <mesh/MeshNodeBoundary.hpp>
+#include <mesh/MeshNodeZone.hpp>
 #include <scheme/DirichletBoundaryConditionDescriptor.hpp>
 #include <scheme/DiscreteFunctionVariant.hpp>
 #include <scheme/FixedBoundaryConditionDescriptor.hpp>
@@ -24,6 +25,34 @@
 
 CouplageModule::CouplageModule()
 {
+  this->_addBuiltinFunction("serialize_new",
+                            std::function(
+                              [](std::shared_ptr<const IMesh> i_mesh,
+                                 const std::vector<std::shared_ptr<const IZoneDescriptor>>& i_zone_list) -> void {
+                                for (const auto& i_zone : i_zone_list) {
+                                  const int tag                = 10;
+                                  using MeshType               = Mesh<Connectivity<2>>;
+                                  const std::shared_ptr p_mesh = std::dynamic_pointer_cast<const MeshType>(i_mesh);
+
+                                  auto mesh_node_zone = getMeshNodeZone(*p_mesh, *i_zone);
+                                  std::cout << "\033[01;31m"
+                                            << "mesh_node_zone" << mesh_node_zone << "\033[00;00m" << std::endl;
+
+                                  /*   for (size_t i_ref_node_list = 0; */
+                                  /*        i_ref_node_list < */
+                                  /*        mesh->connectivity().template numberOfRefItemList<ItemType::edge>(); */
+                                  /*        ++i_ref_node_list) { */
+                                  /*     const auto& ref_node_list = */
+                                  /*       mesh->connectivity().template refItemList<ItemType::edge>(i_ref_node_list);
+                                   */
+                                  /*     const RefId& ref = ref_node_list.refId(); */
+                                  /*     if (ref == i_zone) { */
+                                  /*       return ref_node_list; */
+                                  /*     } */
+                                  /*   } */
+                                }
+                                return;
+                              }));
   this->_addBuiltinFunction("serialize", std::function([](std::shared_ptr<const IMesh> mesh) -> void {
                               const int tag = 10;
                               return Serializer().apply(mesh, tag);
@@ -50,6 +79,12 @@ CouplageModule::CouplageModule()
                               return Serializer().apply(mesh, boundary, field, tag);
                             }));
 
+  this->_addBuiltinFunction("cpl_change_mesh_position",
+                            std::function([](std::shared_ptr<const IMesh> mesh) -> std::shared_ptr<const IMesh> {
+                              const int tag = -1;
+                              return Serializer().change_mesh_position(mesh, tag);
+                            }));
+
   this->_addBuiltinFunction("test", std::function(
 
                                       [](const std::shared_ptr<const IMesh>& i_mesh) -> void {
diff --git a/src/mesh/CMakeLists.txt b/src/mesh/CMakeLists.txt
index 39f31282296315f1dea4647bcb9d02aa43169707..889d5b780d7631c97f483479fc44a3590b7f7035 100644
--- a/src/mesh/CMakeLists.txt
+++ b/src/mesh/CMakeLists.txt
@@ -34,6 +34,7 @@ add_library(
   MeshLineFaceBoundary.cpp
   MeshLineNodeBoundary.cpp
   MeshNodeBoundary.cpp
+  MeshNodeZone.cpp
   MeshRandomizer.cpp
   MeshSmoother.cpp
   MeshTransformer.cpp
diff --git a/src/mesh/MeshBuilderBase.cpp b/src/mesh/MeshBuilderBase.cpp
index 973a6099afb49595d02403c697bbb927d2a7ba63..205feceab31410426c1cace7534868ea4e0b615d 100644
--- a/src/mesh/MeshBuilderBase.cpp
+++ b/src/mesh/MeshBuilderBase.cpp
@@ -188,24 +188,7 @@ MeshBuilderBase::_checkMesh() const
     }
   }
 
-  const auto& Cjr = MeshDataManager::instance().getMeshData(mesh).Cjr();
-  const auto& xr  = mesh.xr();
-
-  for (CellId cell_id = 0; cell_id < mesh.numberOfCells(); ++cell_id) {
-    double cell_volume = 0;
-    auto cell_nodes    = cell_to_node_matrix[cell_id];
-    for (size_t i_node = 0; i_node < cell_nodes.size(); ++i_node) {
-      cell_volume += dot(Cjr(cell_id, i_node), xr[cell_nodes[i_node]]);
-    }
-
-    if (cell_volume <= 0) {
-      std::ostringstream error_msg;
-      error_msg << "invalid mesh.\n\tThe following cell\n";
-      error_msg << "\t - id=" << cell_id << " number=" << connectivity.cellNumber()[cell_id] << '\n';
-      error_msg << "\thas non-positive volume: " << cell_volume / Dimension;
-      throw NormalError(error_msg.str());
-    }
-  }
+  MeshDataManager::instance().getMeshData(mesh).Vj();
 }
 
 template void MeshBuilderBase::_checkMesh<1>() const;
diff --git a/src/mesh/MeshNodeBoundary.cpp b/src/mesh/MeshNodeBoundary.cpp
index 3e01616c66670706449018107aa3d417ab1d5007..8d72a669ff181b7e4ea2fbc466eddaf92f10941f 100644
--- a/src/mesh/MeshNodeBoundary.cpp
+++ b/src/mesh/MeshNodeBoundary.cpp
@@ -296,30 +296,29 @@ getMeshNodeBoundary(const Mesh<Connectivity<Dimension>>& mesh, const IBoundaryDe
     if (ref == boundary_descriptor) {
       return MeshNodeBoundary<Dimension>{mesh, ref_node_list};
     }
-  }
-  for (size_t i_ref_edge_list = 0; i_ref_edge_list < mesh.connectivity().template numberOfRefItemList<ItemType::edge>();
-       ++i_ref_edge_list) {
-    const auto& ref_edge_list = mesh.connectivity().template refItemList<ItemType::edge>(i_ref_edge_list);
-    const RefId& ref          = ref_edge_list.refId();
-    if (ref == boundary_descriptor) {
-      return MeshNodeBoundary<Dimension>{mesh, ref_edge_list};
+    for (size_t i_ref_edge_list = 0;
+         i_ref_edge_list < mesh.connectivity().template numberOfRefItemList<ItemType::edge>(); ++i_ref_edge_list) {
+      const auto& ref_edge_list = mesh.connectivity().template refItemList<ItemType::edge>(i_ref_edge_list);
+      const RefId& ref          = ref_edge_list.refId();
+      if (ref == boundary_descriptor) {
+        return MeshNodeBoundary<Dimension>{mesh, ref_edge_list};
+      }
     }
-  }
-  for (size_t i_ref_face_list = 0; i_ref_face_list < mesh.connectivity().template numberOfRefItemList<ItemType::face>();
-       ++i_ref_face_list) {
-    const auto& ref_face_list = mesh.connectivity().template refItemList<ItemType::face>(i_ref_face_list);
-    const RefId& ref          = ref_face_list.refId();
-    if (ref == boundary_descriptor) {
-      return MeshNodeBoundary<Dimension>{mesh, ref_face_list};
+    for (size_t i_ref_face_list = 0;
+         i_ref_face_list < mesh.connectivity().template numberOfRefItemList<ItemType::face>(); ++i_ref_face_list) {
+      const auto& ref_face_list = mesh.connectivity().template refItemList<ItemType::face>(i_ref_face_list);
+      const RefId& ref          = ref_face_list.refId();
+      if (ref == boundary_descriptor) {
+        return MeshNodeBoundary<Dimension>{mesh, ref_face_list};
+      }
     }
-  }
 
-  std::ostringstream ost;
-  ost << "cannot find node list with name " << rang::fgB::red << boundary_descriptor << rang::style::reset;
+    std::ostringstream ost;
+    ost << "cannot find node list with name " << rang::fgB::red << boundary_descriptor << rang::style::reset;
 
-  throw NormalError(ost.str());
-}
+    throw NormalError(ost.str());
+  }
 
-template MeshNodeBoundary<1> getMeshNodeBoundary(const Mesh<Connectivity<1>>&, const IBoundaryDescriptor&);
-template MeshNodeBoundary<2> getMeshNodeBoundary(const Mesh<Connectivity<2>>&, const IBoundaryDescriptor&);
-template MeshNodeBoundary<3> getMeshNodeBoundary(const Mesh<Connectivity<3>>&, const IBoundaryDescriptor&);
+  template MeshNodeBoundary<1> getMeshNodeBoundary(const Mesh<Connectivity<1>>&, const IBoundaryDescriptor&);
+  template MeshNodeBoundary<2> getMeshNodeBoundary(const Mesh<Connectivity<2>>&, const IBoundaryDescriptor&);
+  template MeshNodeBoundary<3> getMeshNodeBoundary(const Mesh<Connectivity<3>>&, const IBoundaryDescriptor&);
diff --git a/src/mesh/MeshNodeZone.cpp b/src/mesh/MeshNodeZone.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..9c2c3599e3742a120ab40ed16e3d3f4105ee454a
--- /dev/null
+++ b/src/mesh/MeshNodeZone.cpp
@@ -0,0 +1,42 @@
+#include <mesh/MeshNodeZone.hpp>
+
+#include <mesh/Connectivity.hpp>
+#include <mesh/Mesh.hpp>
+#include <utils/Messenger.hpp>
+
+template <size_t Dimension>
+MeshNodeZone<Dimension>::MeshNodeZone(const Mesh<Connectivity<Dimension>>&, const RefNodeList& ref_node_list)
+  : m_node_list(ref_node_list.list()), m_zone_name(ref_node_list.refId().tagName())
+{}
+
+template <size_t Dimension>
+// MeshNodeZone<Dimension>
+int
+getMeshNodeZone(const Mesh<Connectivity<Dimension>>& mesh, const IZoneDescriptor& zone_descriptor)
+{
+  for (size_t i_ref_edge_list = 0; i_ref_edge_list < mesh.connectivity().template numberOfRefItemList<ItemType::edge>();
+       ++i_ref_edge_list) {
+    const auto& ref_edge_list = mesh.connectivity().template refItemList<ItemType::edge>(i_ref_edge_list);
+
+    const RefId& ref = ref_edge_list.refId();
+    if (ref == zone_descriptor) {
+      std::cout << "\033[01;31m"
+                << "ref" << ref << "\033[00;00m" << std::endl;
+      return 1;
+      /* return MeshNodeZone<Dimension>{mesh, ref_node_list}; */
+    }
+  }
+
+  std::ostringstream ost;
+  ost << "cannot find node set with name \"" << rang::fgB::red << zone_descriptor << rang::style::reset << '\"';
+
+  throw NormalError(ost.str());
+}
+
+/* template MeshNodeZone<1> getMeshNodeZone(const Mesh<Connectivity<1>>&, const IZoneDescriptor&); */
+/* template MeshNodeZone<2> getMeshNodeZone(const Mesh<Connectivity<2>>&, const IZoneDescriptor&); */
+/* template MeshNodeZone<3> getMeshNodeZone(const Mesh<Connectivity<3>>&, const IZoneDescriptor&); */
+
+template int getMeshNodeZone(const Mesh<Connectivity<1>>&, const IZoneDescriptor&);
+template int getMeshNodeZone(const Mesh<Connectivity<2>>&, const IZoneDescriptor&);
+template int getMeshNodeZone(const Mesh<Connectivity<3>>&, const IZoneDescriptor&);
diff --git a/src/mesh/MeshNodeZone.hpp b/src/mesh/MeshNodeZone.hpp
new file mode 100644
index 0000000000000000000000000000000000000000..14d6295f84e7d0c7bf31ee57216f6bf9ca32a2bf
--- /dev/null
+++ b/src/mesh/MeshNodeZone.hpp
@@ -0,0 +1,53 @@
+#ifndef MESH_NODE_ZONE_HPP
+#define MESH_NODE_ZONE_HPP
+
+#include <mesh/IZoneDescriptor.hpp>
+#include <mesh/RefItemList.hpp>
+#include <utils/Array.hpp>
+
+template <size_t Dimension>
+class Connectivity;
+
+template <typename ConnectivityType>
+class Mesh;
+
+template <size_t Dimension>
+class [[nodiscard]] MeshNodeZone   // clazy:exclude=copyable-polymorphic
+{
+ protected:
+  Array<const NodeId> m_node_list;
+  std::string m_zone_name;
+
+ public:
+  template <size_t MeshDimension>
+  friend MeshNodeZone<MeshDimension> getMeshNodeZone(const Mesh<Connectivity<MeshDimension>>& mesh,
+                                                     const IZoneDescriptor& zone_descriptor);
+
+  MeshNodeZone& operator=(const MeshNodeZone&) = default;
+  MeshNodeZone& operator=(MeshNodeZone&&)      = default;
+
+  const Array<const NodeId>&
+  nodeList() const
+  {
+    return m_node_list;
+  }
+
+ protected:
+  MeshNodeZone(const Mesh<Connectivity<Dimension>>& mesh, const RefNodeList& ref_node_list);
+
+ public:
+  MeshNodeZone(const MeshNodeZone&) = default;
+  MeshNodeZone(MeshNodeZone&&)      = default;
+
+  MeshNodeZone()          = default;
+  virtual ~MeshNodeZone() = default;
+};
+
+/* template <size_t Dimension> */
+/* MeshNodeZone<Dimension> getMeshNodeZone(const Mesh<Connectivity<Dimension>>& mesh, */
+/*                                         const IZoneDescriptor& zone_descriptor); */
+
+template <size_t Dimension>
+int getMeshNodeZone(const Mesh<Connectivity<Dimension>>& mesh, const IZoneDescriptor& zone_descriptor);
+
+#endif   // MESH_NODE_ZONE_HPP
diff --git a/src/scheme/DiscreteFunctionVectorIntegrator.cpp b/src/scheme/DiscreteFunctionVectorIntegrator.cpp
index 80b9e711ebfe9e45297e1a01a1d63ad37da72914..15de7a5a3c83dbcff468db587949366786122fc9 100644
--- a/src/scheme/DiscreteFunctionVectorIntegrator.cpp
+++ b/src/scheme/DiscreteFunctionVectorIntegrator.cpp
@@ -1,3 +1,4 @@
+
 #include <scheme/DiscreteFunctionVectorIntegrator.hpp>
 
 #include <language/utils/IntegrateCellArray.hpp>
diff --git a/src/utils/Serializer.cpp b/src/utils/Serializer.cpp
index 250b2a6fa1ac2d78905a6cc80dff462e4198ab02..d8b79bc92b97a3e6dd4f0e047f99794ecca1d1c5 100644
--- a/src/utils/Serializer.cpp
+++ b/src/utils/Serializer.cpp
@@ -406,4 +406,65 @@ Serializer::apply(const std::shared_ptr<const IBoundaryDescriptor>& boundary,
   }
   }
 }
-#endif   // PUGS_HAS_COSTO
+
+std::shared_ptr<const IMesh>
+Serializer::change_mesh_position(std::shared_ptr<const IMesh> i_mesh, const int tag)
+{
+  const int src = 1;
+  std::vector<double> recv_xr;
+  parallel::Messenger::getInstance().myCoupling->recvData(recv_xr, src, tag);
+
+  switch (i_mesh->dimension()) {
+  case 1: {
+    using MeshType                   = Mesh<Connectivity<1>>;
+    const std::shared_ptr given_mesh = std::dynamic_pointer_cast<const MeshType>(i_mesh);
+    using Rd                         = TinyVector<MeshType::Dimension>;
+    /* const NodeValue<const Rd>& xr    = given_mesh->xr(); */
+
+    NodeValue<Rd> new_xr{given_mesh->connectivity()};
+    parallel_for(
+      given_mesh->numberOfNodes(), PUGS_LAMBDA(const NodeId node_id) {
+        for (unsigned short j = 0; j < MeshType::Dimension; ++j) {
+          /* new_xr[node_id][j] = xr[node_id][j]; */
+          new_xr[node_id][j] = recv_xr[MeshType::Dimension * node_id + j];
+        }
+      });
+
+    return std::make_shared<MeshType>(given_mesh->shared_connectivity(), new_xr);
+  }
+  case 2: {
+    using MeshType                   = Mesh<Connectivity<2>>;
+    const std::shared_ptr given_mesh = std::dynamic_pointer_cast<const MeshType>(i_mesh);
+    using Rd                         = TinyVector<MeshType::Dimension>;
+    /* const NodeValue<const Rd>& xr    = given_mesh->xr(); */
+
+    NodeValue<Rd> new_xr{given_mesh->connectivity()};
+    parallel_for(
+      given_mesh->numberOfNodes(), PUGS_LAMBDA(const NodeId node_id) {
+        for (unsigned short j = 0; j < MeshType::Dimension; ++j) {
+          /* new_xr[node_id][j] = xr[node_id][j]; */
+          new_xr[node_id][j] = recv_xr[MeshType::Dimension * node_id + j];
+        }
+      });
+
+    return std::make_shared<MeshType>(given_mesh->shared_connectivity(), new_xr);
+  }
+  case 3: {
+    using MeshType                   = Mesh<Connectivity<3>>;
+    const std::shared_ptr given_mesh = std::dynamic_pointer_cast<const MeshType>(i_mesh);
+    using Rd                         = TinyVector<MeshType::Dimension>;
+    /* const NodeValue<const Rd>& xr    = given_mesh->xr(); */
+
+    NodeValue<Rd> new_xr{given_mesh->connectivity()};
+    parallel_for(
+      given_mesh->numberOfNodes(), PUGS_LAMBDA(const NodeId node_id) {
+        for (unsigned short j = 0; j < MeshType::Dimension; ++j) {
+          /* new_xr[node_id][j] = xr[node_id][j]; */
+          new_xr[node_id][j] = recv_xr[MeshType::Dimension * node_id + j];
+        }
+      });
+
+    return std::make_shared<MeshType>(given_mesh->shared_connectivity(), new_xr);
+  }
+  }
+}
diff --git a/src/utils/Serializer.hpp b/src/utils/Serializer.hpp
index 0273930f78adb40299a258087b0864ebc4e6b137..5c372873dced3821527b30e66f99768dbe917bbb 100644
--- a/src/utils/Serializer.hpp
+++ b/src/utils/Serializer.hpp
@@ -51,6 +51,8 @@ class Serializer
   void apply(const std::shared_ptr<const IBoundaryDescriptor>& boundary,
              const std::shared_ptr<const DiscreteFunctionVariant>& field,
              const int tag);
+
+  std::shared_ptr<const IMesh> change_mesh_position(std::shared_ptr<const IMesh> i_mesh, const int tag);
 };
 
 #endif   // PUGS_HAS_COSTO