diff --git a/src/coupling/arlequin_template.cc b/src/coupling/arlequin_template.cc
index 4239ae6..df8144a 100644
--- a/src/coupling/arlequin_template.cc
+++ b/src/coupling/arlequin_template.cc
@@ -1,182 +1,158 @@
 /**
  * @file   arlequin_template.cc
  *
  * @author Guillaume Anciaux <guillaume.anciaux@epfl.ch>
  *
  * @date   Mon Nov 25 15:05:56 2013
  *
  * @brief  Internal class to factor code for the Arlequin kind methods
  *
  * @section LICENSE
  *
  * Copyright INRIA and CEA
  *
  * The LibMultiScale is a C++ parallel framework for the multiscale
  * coupling methods dedicated to material simulations. This framework
  * provides an API which makes it possible to program coupled simulations
  * and integration of already existing codes.
  *
  * This Project was initiated in a collaboration between INRIA Futurs Bordeaux
  * within ScAlApplix team and CEA/DPTA Ile de France.
  * The project is now continued at the Ecole Polytechnique Fédérale de Lausanne
  * within the LSMS/ENAC laboratory.
  *
  * This software is governed by the CeCILL-C license under French law and
  * abiding by the rules of distribution of free software.  You can  use,
  * modify and/ or redistribute the software under the terms of the CeCILL-C
  * license as circulated by CEA, CNRS and INRIA at the following URL
  * "http://www.cecill.info".
  *
  * As a counterpart to the access to the source code and  rights to copy,
  * modify and redistribute granted by the license, users are provided only
  * with a limited warranty  and the software's author,  the holder of the
  * economic rights,  and the successive licensors  have only  limited
  * liability.
  *
  * In this respect, the user's attention is drawn to the risks associated
  * with loading,  using,  modifying and/or developing or reproducing the
  * software by the user in light of its specific status of free software,
  * that may mean  that it is complicated to manipulate,  and  that  also
  * therefore means  that it is reserved for developers  and  experienced
  * professionals having in-depth computer knowledge. Users are therefore
  * encouraged to load and test the software's suitability as regards their
  * requirements in conditions enabling the security of their systems and/or
  * data to be ensured and,  more generally, to use and operate it in the
  * same conditions as regards security.
  *
  * The fact that you are presently reading this means that you have had
  * knowledge of the CeCILL-C license and that you accept its terms.
  *
  */
 
 /* -------------------------------------------------------------------------- */
 #include "arlequin_template.hh"
 #include "bridging.hh"
 #include "bridging_atomic_continuum.hh"
 #include "factory_multiscale.hh"
 #include "lm_common.hh"
 #include <fstream>
 /* -------------------------------------------------------------------------- */
 __BEGIN_LIBMULTISCALE__
 
 ArlequinTemplate::ArlequinTemplate(const std::string &name)
     : LMObject(name), CouplingAtomicContinuum(name),
       bridging_zone(this->getID() + "-bridging"),
       boundary_zone(this->getID() + "-boundary"),
       weight_mesh("weight-mesh-" + name), weight_point("weight-point-" + name),
       lambdas_mesh("lambdas-mesh-" + name),
       lambdas_point("lambdas-point-" + name) {
 
   this->weight_mesh.setCommGroup(comm_group_continuum());
   this->lambdas_mesh.setCommGroup(comm_group_continuum());
 
   this->weight_point.setCommGroup(comm_group_atomic());
   this->lambdas_point.setCommGroup(comm_group_atomic());
 
   this->createOutput("weight-mesh") = this->weight_mesh;
   this->createOutput("lambdas-mesh") = this->lambdas_mesh;
   this->createOutput("weight-point") = this->weight_point;
   this->createOutput("lambdas-point") = this->lambdas_point;
 }
 
 /* -------------------------------------------------------------------------- */
-INSTANCIATE_DISPATCH(ArlequinTemplate::computeWeights)
-template <typename ContA, typename ContC>
-void ArlequinTemplate::computeWeights(ContA &pointList, ContC &meshList) {
+INSTANCIATE_DISPATCH(ArlequinTemplate::computeAtomicWeights)
+template <typename ContA>
+void ArlequinTemplate::computeAtomicWeights(ContA &pointList) {
 
   // point weights
-  if (this->is_in_atomic()) {
-    this->weight_point.compute(pointList);
-    bridging_zone.attachVector(this->weight_point.evalArrayOutput());
+  this->weight_point.compute(pointList);
+  bridging_zone.attachVector(this->weight_point.evalArrayOutput());
 
-    lambdas_point.assign(weight_point.evalArrayOutput().size(), 0);
-    this->bridging_zone.attachVector(lambdas_point);
+  lambdas_point.assign(weight_point.evalArrayOutput().size(), 0);
+  this->bridging_zone.attachVector(lambdas_point);
 
-    auto &&weights = weight_point.evalArrayOutput();
+  auto &&weights = weight_point.evalArrayOutput();
 
-    for (auto &&[at, lbda, weight] : zip(pointList, lambdas_point, weights)) {
-      lbda = weight * at.mass();
-    }
+  for (auto &&[at, lbda, weight] : zip(pointList, lambdas_point, weights)) {
+    lbda = weight * at.mass();
   }
+}
+/* -------------------------------------------------------------------------- */
+
+INSTANCIATE_DISPATCH(ArlequinTemplate::computeContinuumWeights)
+template <typename ContC>
+void ArlequinTemplate::computeContinuumWeights(ContC &meshList) {
 
   // mesh weights
-  if (this->is_in_continuum()) {
 
-    this->weight_mesh.compute(meshList);
-    lambdas_mesh.assign(weight_mesh.evalArrayOutput().size(), 0);
+  this->weight_mesh.compute(meshList);
+  lambdas_mesh.assign(weight_mesh.evalArrayOutput().size(), 0);
 
-    for (auto &&[nd, lbda, weight] :
-         zip(meshList.getContainerNodes(), lambdas_mesh,
-             weight_mesh.evalArrayOutput())) {
-      lbda = weight * nd.mass();
-    }
+  for (auto &&[nd, lbda, weight] :
+       zip(meshList.getContainerNodes(), lambdas_mesh,
+           weight_mesh.evalArrayOutput())) {
+    lbda = weight * nd.mass();
   }
 }
 /* -------------------------------------------------------------------------- */
 
-// void ArlequinTemplate::allocate(UInt t) {
-//   size_constraint = t;
-// const UInt Dim = spatial_dimension;
-// DUMP("initial number of atoms in rec " << size_constraint,
-// DBG_INFO_STARTUP); DUMP("allocation of " << Dim * (size_constraint) << "
-// Reals",
-//      DBG_INFO_STARTUP);
-// A.assign(size_constraint, 0);
-// rhs.resize(size_constraint, Dim);
-// rhs.array().setZero();
-
-// DUMP("Attach vector A", DBG_INFO_STARTUP);
-// bridging_zone.attachVector(A);
-//}
-
-/* -------------------------------------------------------------------------- */
-
-// void ArlequinTemplate::cleanRHS() {
-//   rhs.resize(this->bridging_zone.getNumberLocalMatchedPoints(),
-//              spatial_dimension);
-//   rhs.array().setZero();
-// }
-
-// /* --------------------------------------------------------------------------
-// */
-
 /* LMDESC ArlequinTemplate
    This class is used internally.
 
    It is to be used
    while two zones are declared, one for the coupling
    and one for providing a stiff boundary condition to the atoms.
    In the coupling a linear weight function is built.
 */
 
 /* LMHERITANCE dof_association compute_arlequin_weight */
 
 void ArlequinTemplate::declareParams() {
 
   this->addSubParsableObject(bridging_zone);
   this->addSubParsableObject(boundary_zone);
   this->addSubParsableObject(weight_mesh);
   this->addSubParsableObject(weight_point);
 
   /* LMKEYWORD GEOMETRY
    Set the bridging/overlaping zone where the Lagrange multipliers are
    to be computed.
   */
   this->parseKeyword("GEOMETRY", bridging_geom);
 
   /* LMKEYWORD BOUNDARY
      Set the boundary geometry where the atom velocities are to be fixed from
      the interpolated finite element velocities.
   */
   this->parseKeyword("BOUNDARY", boundary_geom);
 
   /* LMKEYWORD CHECK_COHERENCY
      Perform a systematic check of the communication scheme.
      **Careful, it is computationally expensive**
   */
   this->parseTag("CHECK_COHERENCY", check_coherency, false);
 }
 
 /* ------------------------------------------------------------------------ */
 
 __END_LIBMULTISCALE__
diff --git a/src/coupling/arlequin_template.hh b/src/coupling/arlequin_template.hh
index 6826a6d..3b28026 100644
--- a/src/coupling/arlequin_template.hh
+++ b/src/coupling/arlequin_template.hh
@@ -1,103 +1,105 @@
 /**
  * @file   arlequin_template.hh
  *
  * @author Guillaume Anciaux <guillaume.anciaux@epfl.ch>
  *
  * @date   Mon Nov 25 15:05:56 2013
  *
  * @brief  Internal class to factor code for the Arlequin kind methods
  *
  * @section LICENSE
  *
  * Copyright INRIA and CEA
  *
  * The LibMultiScale is a C++ parallel framework for the multiscale
  * coupling methods dedicated to material simulations. This framework
  * provides an API which makes it possible to program coupled simulations
  * and integration of already existing codes.
  *
  * This Project was initiated in a collaboration between INRIA Futurs Bordeaux
  * within ScAlApplix team and CEA/DPTA Ile de France.
  * The project is now continued at the Ecole Polytechnique Fédérale de Lausanne
  * within the LSMS/ENAC laboratory.
  *
  * This software is governed by the CeCILL-C license under French law and
  * abiding by the rules of distribution of free software.  You can  use,
  * modify and/ or redistribute the software under the terms of the CeCILL-C
  * license as circulated by CEA, CNRS and INRIA at the following URL
  * "http://www.cecill.info".
  *
  * As a counterpart to the access to the source code and  rights to copy,
  * modify and redistribute granted by the license, users are provided only
  * with a limited warranty  and the software's author,  the holder of the
  * economic rights,  and the successive licensors  have only  limited
  * liability.
  *
  * In this respect, the user's attention is drawn to the risks associated
  * with loading,  using,  modifying and/or developing or reproducing the
  * software by the user in light of its specific status of free software,
  * that may mean  that it is complicated to manipulate,  and  that  also
  * therefore means  that it is reserved for developers  and  experienced
  * professionals having in-depth computer knowledge. Users are therefore
  * encouraged to load and test the software's suitability as regards their
  * requirements in conditions enabling the security of their systems and/or
  * data to be ensured and,  more generally, to use and operate it in the
  * same conditions as regards security.
  *
  * The fact that you are presently reading this means that you have had
  * knowledge of the CeCILL-C license and that you accept its terms.
  *
  */
 
 #ifndef __LIBMULTISCALE_ARLEQUIN_TEMPLATE_HH__
 #define __LIBMULTISCALE_ARLEQUIN_TEMPLATE_HH__
 /* -------------------------------------------------------------------------- */
 #include "bridging_atomic_continuum.hh"
 #include "compute_arlequin_weight.hh"
 #include "coupling_atomic_continuum.hh"
 #include "lib_continuum.hh"
 #include "lib_md.hh"
 /* -------------------------------------------------------------------------- */
 __BEGIN_LIBMULTISCALE__
 
 class ArlequinTemplate : public CouplingAtomicContinuum {
 
 public:
   ArlequinTemplate(const std::string &name);
   ~ArlequinTemplate() = default;
   void declareParams();
 
   //! The bridging zone
   BridgingAtomicContinuum bridging_zone;
   //! The bridge zone used for surface effects
   BridgingAtomicContinuum boundary_zone;
 
 protected:
-  DECORATE_FUNCTION_DISPATCH(computeWeights, subMD, subCONTINUUM)
+  DECORATE_FUNCTION_DISPATCH(computeAtomicWeights, subMD)
   //! Compute the weighting function of the coupled MD DOFs
-  template <typename ContA, typename ContC>
-  void computeWeights(ContA &pointList, ContC &meshList);
+  template <typename ContA> void computeAtomicWeights(ContA &pointList);
+  DECORATE_FUNCTION_DISPATCH(computeContinuumWeights, subCONTINUUM)
+  //! Compute the weighting function of the coupled MD DOFs
+  template <typename ContC> void computeContinuumWeights(ContC &meshList);
 
 protected:
   //! geometry id for the bridging zone
   LMID bridging_geom;
   //! geometry id for the boundary zone
   LMID boundary_geom;
 
   //! weighting vector for FE DOFs
   ComputeArlequinWeight weight_mesh;
   //! weighting vector for MD DOFs
   ComputeArlequinWeight weight_point;
 
   //! weighting vector for FE DOFs
   ContainerArray<Real> lambdas_mesh;
   //! weighting vector for MD DOFs
   ContainerArray<Real> lambdas_point;
 
   //! flag to know wether we have to chack for coherency
   bool check_coherency;
 };
 /* -------------------------------------------------------------------------- */
 __END_LIBMULTISCALE__
 /* -------------------------------------------------------------------------- */
 #endif /* __LIBMULTISCALE_ARLEQUIN_TEMPLATE_HH__ */
diff --git a/src/coupling/bridging.cc b/src/coupling/bridging.cc
index 63da7f0..f9f6622 100644
--- a/src/coupling/bridging.cc
+++ b/src/coupling/bridging.cc
@@ -1,417 +1,416 @@
 /**
  * @file   bridging.cc
  *
  * @author Guillaume Anciaux <guillaume.anciaux@epfl.ch>
  *
  * @date   Fri Jul 11 15:47:44 2014
  *
  * @brief  Bridging object between atomistic and finite elements
  *
  * @section LICENSE
  *
  * Copyright INRIA and CEA
  *
  * The LibMultiScale is a C++ parallel framework for the multiscale
  * coupling methods dedicated to material simulations. This framework
  * provides an API which makes it possible to program coupled simulations
  * and integration of already existing codes.
  *
  * This Project was initiated in a collaboration between INRIA Futurs Bordeaux
  * within ScAlApplix team and CEA/DPTA Ile de France.
  * The project is now continued at the Ecole Polytechnique Fédérale de Lausanne
  * within the LSMS/ENAC laboratory.
  *
  * This software is governed by the CeCILL-C license under French law and
  * abiding by the rules of distribution of free software.  You can  use,
  * modify and/ or redistribute the software under the terms of the CeCILL-C
  * license as circulated by CEA, CNRS and INRIA at the following URL
  * "http://www.cecill.info".
  *
  * As a counterpart to the access to the source code and  rights to copy,
  * modify and redistribute granted by the license, users are provided only
  * with a limited warranty  and the software's author,  the holder of the
  * economic rights,  and the successive licensors  have only  limited
  * liability.
  *
  * In this respect, the user's attention is drawn to the risks associated
  * with loading,  using,  modifying and/or developing or reproducing the
  * software by the user in light of its specific status of free software,
  * that may mean  that it is complicated to manipulate,  and  that  also
  * therefore means  that it is reserved for developers  and  experienced
  * professionals having in-depth computer knowledge. Users are therefore
  * encouraged to load and test the software's suitability as regards their
  * requirements in conditions enabling the security of their systems and/or
  * data to be ensured and,  more generally, to use and operate it in the
  * same conditions as regards security.
  *
  * The fact that you are presently reading this means that you have had
  * knowledge of the CeCILL-C license and that you accept its terms.
  *
  */
 
 /* -------------------------------------------------------------------------- */
 #include "bridging.hh"
 #include "compute_extract.hh"
 #include "factory_multiscale.hh"
 #include "filter_geometry.hh"
 #include "geometry_manager.hh"
 #include "lm_common.hh"
 #include "trace_atom.hh"
 /* -------------------------------------------------------------------------- */
 __BEGIN_LIBMULTISCALE__
 
 Bridging::Bridging(const std::string &name)
     : LMObject(name), DofAssociation(name),
       unmatchedPointList("unmatchedPointList-" + name),
       unmatchedMeshList("unmatchedMeshList-" + name),
       pointList(createOutput("pointList")), meshList(createOutput("meshList")),
       contMesh(createOutput("contMesh")), grid(createOutput("grid")) {
   assoc_found = 0;
 
   unmatchedPointList.setCommGroup(this->comm_group_A);
   unmatchedMeshList.setCommGroup(this->comm_group_B);
 
   // contains the elements selected by geometry
   this->createOutput("unmatchedMeshList") = unmatchedMeshList;
   // contains the points selected by geometry
   this->createOutput("unmatchedPointList") = unmatchedPointList;
 }
 /* -------------------------------------------------------------------------- */
 Bridging::~Bridging() {}
 /* -------------------------------------------------------------------------- */
 
 void Bridging::filterArray(ContainerArray<Real> &array) {
   UInt index = 0;
   for (UInt i = 0; i < pointToElement.size(); ++i)
     if (pointToElement[i] != UINT_MAX) {
       DUMP("for container, atom " << i << " becomes " << index, DBG_ALL);
       LM_ASSERT(i < array.size() && index < array.size(),
                 "overflow detected: nmax = " << array.size() << " , index = "
                                              << index << " and i = " << i);
 
       array(index) = array(i);
       ++index;
     }
 }
 /* -------------------------------------------------------------------------- */
 // void Bridging::cumulPBC(ContainerArray<Real> &data) {
 
 //   UInt npairs [[gnu::unused]] = local_pbc_pairs.size();
 //   DUMP("Detected " << npairs << " local pairs", DBG_INFO);
 //   for (auto &&pair : local_pbc_pairs) {
 //     UInt i1 = pair.first;
 //     UInt i2 = pair.second;
 
 //     data(i2) += data(i1);
 //   }
 //   for (auto &&pair : local_pbc_pairs) {
 //     UInt i1 = pair.first;
 //     UInt i2 = pair.second;
 //     data(i1) = data(i2);
 //   }
 // }
 
 /* -------------------------------------------------------------------------- */
 
 void Bridging::mesh2Point(const ContainerArray<Real> &data_node,
                           ContainerArray<Real> &data_atom) {
   if (this->local_points == 0) {
     DUMP("Warning : atomic container is empty:"
              << " cannot interpolate mesh fields on control points (check "
                 "geometries ?!)",
          DBG_WARNING);
     return;
   }
   data_atom = smatrix.transpose() * data_node.matrix();
 }
 
 /* -------------------------------------------------------------------------- */
 
 void Bridging::mesh2Point(FieldType field_type,
                           ContainerArray<Real> &data_point) {
 
   ComputeExtract extracted_field("ComputeExtract:" + this->getID());
   extracted_field.setParam("FIELD", field_type);
   extracted_field.compute(this->meshList);
   this->mesh2Point(extracted_field.evalArrayOutput(), data_point);
 }
 
 /* -------------------------------------------------------------------------- */
 
 void Bridging::leastSquarePointData(ContainerArray<Real> &,
                                     ContainerArray<Real> &, UInt) {
   LM_TOIMPLEMENT;
 }
 /* -------------------------------------------------------------------------- */
 
 void Bridging::copySlaveValues(ContainerArray<Real> &v) {
   for (auto &&pair : local_pbc_pairs) {
     UInt i1 = pair.first;
     UInt i2 = pair.second;
     v(i1) = v(i2);
   }
 }
 
 /* -------------------------------------------------------------------------- */
 /* Parallel Methods                                                           */
 /* -------------------------------------------------------------------------- */
 
 void Bridging::commPoint2Continuum(ContainerArray<Real> &buf) {
   if (this->local_points != 0) {
     this->distributeVectorA2B("communicate buffer", buf);
   }
 }
 /* -------------------------------------------------------------------------- */
 
 void Bridging::commContinuum2Point(ContainerArray<Real> &buf) {
   if (this->local_points != 0) {
     this->distributeVectorB2A("communicate buffer", buf);
   }
 }
 /* -------------------------------------------------------------------------- */
 
 void Bridging::synchSumBuffer(ContainerArray<Real> &buf) {
   if (this->local_points != 0) {
     this->synchronizeVectorBySum("synchsumvector", buf);
   }
 }
 /* -------------------------------------------------------------------------- */
 
 void Bridging::filterRejectedContinuumOwners(
     std::vector<std::vector<UInt>> &unassociated_atoms) {
   if (this->comm_group_A == this->comm_group_B)
     return;
 
   if (not this->in_group_B())
     return;
 
   DUMP("local points", DBG_MESSAGE);
 
   if (this->local_points == 0)
     return;
 
   // loop through the unassociated atoms declared per each processor
   // The total list of atom index rejected is constructed
 
   UInt offset = 0;
   UInt cpt_unassociated = 0;
   std::vector<UInt> atom_to_remove;
 
   for (auto &&[proc, c_w] : enumerate(com_with)) {
     if (not c_w)
       continue;
 
     DUMP("atomic processor " << proc << " unassociated "
                              << unassociated_atoms[proc].size() << " atoms ",
          DBG_INFO_STARTUP);
     for (auto &&unassociated : unassociated_atoms[proc]) {
       // reconstruct the index for atom declared unassociated
       UInt unassociated_index = offset + unassociated;
       atom_to_remove.push_back(unassociated_index);
       pointToElement[unassociated_index] = UINT_MAX;
       // auto el_index = this->pointToElement[unassociated_index];
 
       // LM_ASSERT(el_index != UINT_MAX,
       //           "this should not happend !! " << unassociated_index);
 
       // // remove the column associated to atom in the shapematrix
       // this->smatrix.removeAtom(unassociated_index);
       // // alter the atom-element mapping
       // pointToElement[unassociated_index] = UINT_MAX;
       ++cpt_unassociated;
       DUMP("unassociated atom at position "
                << unassociated_index << " whereas offset = " << offset
                << " next offset is " << offset + this->nb_points_per_proc[proc],
            DBG_INFO_STARTUP);
     }
     offset += this->nb_points_per_proc[proc];
   }
 
   smatrix.removeAtoms(atom_to_remove);
 
   // corrects the local_points variable
   if (cpt_unassociated) {
     DUMP("removed " << cpt_unassociated
                     << " atoms from unassociation. Now local atoms is "
                     << this->local_points,
          DBG_MESSAGE);
     this->local_points -= cpt_unassociated;
     DUMP("and becomes " << this->local_points, DBG_MESSAGE);
   }
 
   // compute contiguous indexes for atoms (compression of indexes)
   // the result is a mapping from old indexes to new ones
   // output: mapping_old_to_new_indexes
   // std::vector<UInt> mapping_old_to_new_indexes;
   // mapping_old_to_new_indexes.assign(pointToElement.size(), UINT_MAX);
   // UInt indirection = 0;
   // for (auto &&[at_index, el_index] : enumerate(pointToElement)) {
   //   if (el_index == UINT_MAX)
   //     continue;
   //   mapping_old_to_new_indexes[at_index] = indirection;
   //   ++indirection;
   // }
   // LM_ASSERT(indirection == this->local_points, "this should not happend "
   //                                                  << indirection << " "
   //                                                  << this->local_points);
 
   // checks that number of mapped atoms equals local atoms variable
   UInt cpt_tmp = 0;
   for (auto &&el_index : pointToElement) {
     if (el_index != UINT_MAX)
       cpt_tmp++;
   }
   if (cpt_tmp != this->local_points)
     LM_FATAL("biip this should not happend " << cpt_tmp << " "
                                              << this->local_points);
 
   // // now renumber indirection in shapematrix
   // indirection = 0;
   // for (auto &&[at_index, el_index] : enumerate(pointToElement)) {
   //   if (el_index == UINT_MAX)
   //     continue;
 
   //   UInt new_index = mapping_old_to_new_indexes[at_index];
 
   //   LM_ASSERT(new_index != UINT_MAX, "This should not happend");
   //   smatrix.changeAtomIndirection(at_index, new_index, indirection);
   //   ++indirection;
   // }
   // this->smatrix.swapAtomIndirections();
 
   // now i set the duo vector
   this->createDuoVectorB("FE", pointToElement);
 }
 /* -------------------------------------------------------------------------- */
 
 void Bridging::setPBCPairs(std::vector<std::pair<UInt, UInt>> &pairs) {
   if (this->is_in_continuum())
     pbc_pairs = pairs;
 }
 
 /* -------------------------------------------------------------------------- */
 
 UInt Bridging::getNumberPoints() { LM_TOIMPLEMENT; }
 /* -------------------------------------------------------------------------- */
 
 UInt Bridging::getNumberElems() { LM_TOIMPLEMENT; }
 /* -------------------------------------------------------------------------- */
 
 UInt Bridging::getNumberNodes() { LM_TOIMPLEMENT; }
 /* -------------------------------------------------------------------------- */
 
 void Bridging::attachVector(ContainerArray<Real> &tab) {
   this->pointList.get<ContainerInterface>().attachObject(tab);
 }
 /* -------------------------------------------------------------------------- */
 
 void Bridging::updateForMigration() {
   DUMPBYPROC("update migration for " << this->getID(), DBG_INFO, 0);
 
   STARTTIMER("syncMigration resize");
   // update local number of atoms in atomic part
   if (this->in_group_A()) {
     this->local_points =
         this->getOutput<ContainerInterface>("pointList").size();
     this->positions.resize(this->local_points, spatial_dimension);
   }
   STOPTIMER("syncMigration resize");
 
   STARTTIMER("syncMigration duo");
   this->synchronizeMigration(this->comm_group_A, this->comm_group_B);
   STOPTIMER("syncMigration duo");
 
   // pointList.setRelease(this->contA.getRelease());
   // meshList.setRelease(this->contB.getRelease());
 }
 /* -------------------------------------------------------------------------- */
 
 /* LMDESC Bridging
    This class implements a bridging zone where
    point and elements are associated.
 
    For debugging pruposes, several set of DOf are registered to the central
    system:
 
    - unmatched-fe-\${couplerID} : the set of nodes and elements
      that are contained in the geometry provided by GEOMETRY keyword.
    - unmatched-point-\${couplerID} : the set of points
      that are contained in the geometry provided by GEOMETRY keyword.
    - matched-fe-\${couplerID} : the set of nodes and elements
      that are containing at least one point of unmatched-point-\${couplerID}.
    - matched-point-\${couplerID} : the set of points
      that are contained in at least one element of unmatched-fe-\${couplerID}.
 */
 
 /* LMHERITANCE filter_geometry dof_association */
 
 void Bridging::declareParams() {
   this->addSubParsableObject(unmatchedMeshList);
 
   DofAssociation::declareParams();
 }
 /* -------------------------------------------------------------------------- */
 void Bridging::setPointField(FieldType field, ContainerArray<Real> &buffer) {
+  if (not this->is_in_atomic())
+    return;
   StimulationField impose_field("impose_point_field");
   impose_field.setParam("FIELD", field);
   impose_field.compute("dofs"_input = this->pointList, "field"_input = buffer);
 }
 
 /* -------------------------------------------------------------------------- */
 void Bridging::setPointField(FieldType field, Real val, UInt dim) {
-  ContainerArray<Real> data_point(pointList.get<ContainerInterface>().size(),
-                                  dim);
+  ContainerArray<Real> data_point(this->local_points, dim);
   for (auto &&v : data_point.rowwise()) {
     v = val;
   }
   setPointField(field, data_point);
 }
 
 /* -------------------------------------------------------------------------- */
 
 void Bridging::addPointField(FieldType field, ContainerArray<Real> &buffer) {
   StimulationField impose_field("impose_point_field");
   impose_field.setParam("FIELD", field);
   impose_field.setParam("ADDITIVE", true);
   impose_field.compute("dofs"_input = this->pointList, "field"_input = buffer);
 }
 
 /* -------------------------------------------------------------------------- */
 
 void Bridging::setMeshField(FieldType field, ContainerArray<Real> &buffer) {
   StimulationField impose_field("impose_mesh_field");
   impose_field.setParam("FIELD", field);
   impose_field.compute("dofs"_input = this->meshList, "field"_input = buffer);
 }
 
 /* -------------------------------------------------------------------------- */
 
 void Bridging::addMeshField(FieldType field, ContainerArray<Real> &buffer) {
   StimulationField impose_field("impose_mesh_field");
   impose_field.setParam("FIELD", field);
   impose_field.setParam("ADDITIVE", true);
   impose_field.compute("dofs"_input = this->meshList, "field"_input = buffer);
 }
 /* -------------------------------------------------------------------------- */
 
 void Bridging::setPointField(FieldType field, Eigen::VectorXd val) {
-  ContainerArray<Real> data_point(pointList.get<ContainerInterface>().size(),
-                                  val.rows());
+  ContainerArray<Real> data_point(this->local_points, val.rows());
   for (auto &&v : data_point.rowwise()) {
     v = val;
   }
   setPointField(field, data_point);
 }
 
 /* -------------------------------------------------------------------------- */
 
 void Bridging::setMeshField(FieldType field, Eigen::VectorXd val) {
-  ContainerArray<Real> data_mesh(pointList.get<ContainerInterface>().size(),
-                                 val.rows());
+  ContainerArray<Real> data_mesh(this->local_points, val.rows());
   data_mesh = val;
   setPointField(field, data_mesh);
 }
 
 /* -------------------------------------------------------------------------- */
 
 __END_LIBMULTISCALE__
diff --git a/src/coupling/bridging_atomic_continuum.cc b/src/coupling/bridging_atomic_continuum.cc
index 877d458..bc0d408 100644
--- a/src/coupling/bridging_atomic_continuum.cc
+++ b/src/coupling/bridging_atomic_continuum.cc
@@ -1,344 +1,341 @@
 /**
  * @file   bridging_atomic_continuum.cc
  *
  * @author Guillaume Anciaux <guillaume.anciaux@epfl.ch>
  *
  * @date   Mon Oct 28 19:23:14 2013
  *
  * @brief  Bridging object between atomistic and finite elements
  *
  * @section LICENSE
  *
  * Copyright (©) 2010-2011 EPFL (Ecole Polytechnique Fédérale de Lausanne)
  * Laboratory (LSMS - Laboratoire de Simulation en Mécanique des Solides)
  *
  * LibMultiScale is free  software: you can redistribute it and/or  modify it
  * under the
  * terms  of the  GNU Lesser  General Public  License as  published by  the Free
  * Software Foundation, either version 3 of the License, or (at your option) any
  * later version.
  *
  * LibMultiScale is  distributed in the  hope that it  will be useful, but
  * WITHOUT ANY
  * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
  * A  PARTICULAR PURPOSE. See  the GNU  Lesser General  Public License  for more
  * details.
  *
  * You should  have received  a copy  of the GNU  Lesser General  Public License
  * along with LibMultiScale. If not, see <http://www.gnu.org/licenses/>.
  *
  */
 
 /* -------------------------------------------------------------------------- */
 //#define TIMER
 /* -------------------------------------------------------------------------- */
 #include "bridging_atomic_continuum.hh"
 #include "compute_extract.hh"
 #include "lm_common.hh"
 #include "reference_manager.hh"
 #include "trace_atom.hh"
 /* -------------------------------------------------------------------------- */
 __BEGIN_LIBMULTISCALE__
 
 BridgingAtomicContinuum::BridgingAtomicContinuum(const std::string &name)
     : LMObject(name), Bridging(name), comm_group_continuum(this->comm_group_B),
       comm_group_atomic(this->comm_group_A) {}
 /* -------------------------------------------------------------------------- */
 
 BridgingAtomicContinuum::~BridgingAtomicContinuum() {}
 
 /* -------------------------------------------------------------------------- */
 
 void BridgingAtomicContinuum::updateForMigration() {
 
   Bridging::updateForMigration();
   if (this->check_coherency) {
     checkPositionCoherency();
   }
 }
 /* -------------------------------------------------------------------------- */
 INSTANCIATE_DISPATCH(BridgingAtomicContinuum::init)
 template <typename DomainA, typename DomainC>
 void BridgingAtomicContinuum::init(DomainA &domA, DomainC &domC) {
 
   auto all_group = Communicator::getCommunicator().getGroup("all");
 
   Bridging::init(domA.getContainer(), domC.getContainer());
 
-  auto &pointList = this->pointList.get<typename DomainA::ContainerSubset>();
-
-  domA.getContainer().addSubSet(pointList);
-
-  DUMP(this->getID() << " : attach duo vector", DBG_MESSAGE);
-
   if (in_group_A()) {
+    auto &pointList = this->pointList.get<typename DomainA::ContainerSubset>();
+    domA.getContainer().addSubSet(pointList);
+    DUMP(this->getID() << " : attach duo vector", DBG_MESSAGE);
     pointList.attachObject(this->getDuoVector());
     DUMP(this->getID() << " : attaching Parent::duo_vector", DBG_INFO);
   }
   all_group.synchronize();
 }
 /* -------------------------------------------------------------------------- */
 
 // void BridgingAtomicContinuum::averageDOFsOnElements(
 //     ContainerArray<Real> &data_mesh, FieldType field) {
 
 //   LM_FATAL("to adapt");
 
 //   if (comm_group_atomic == comm_group_continuum) {
 
 //     ComputeExtract extracted_field("ComputeExtract:" + this->getID());
 //     extracted_field.setParam("FIELD", field);
 //     extracted_field.buildManual(*this->pointList);
 //     this->averageOnElements<dispatch>(extracted_field.getArray(), data_mesh,
 //                                       meshList);
 //     return;
 //   }
 
 //   ComputeExtract extracted_field("ComputeExtract:" + this->getID());
 //   extracted_field.setParam("FIELD", field);
 //   if (this->is_in_atomic)
 //     extracted_field.buildManual(*this->pointList);
 
 //   LM_TOIMPLEMENT;
 //   // extracted_field.resize(Parent::local_points * Dim);
 
 //   /* do communication */
 //   this->communicateBufferAtom2Continuum(extracted_field.getArray());
 
 //   if (this->is_in_continuum)
 //     this->averageOnElements<dispatch>(extracted_field.getArray(), data_mesh,
 //                                       meshList);
 // }
 /* -------------------------------------------------------------------------- */
 
 void BridgingAtomicContinuum::leastSquareAtomicData(
     ContainerArray<Real> &data_mesh, ContainerArray<Real> &data_atom) {
 
   if (comm_group_atomic == comm_group_continuum) {
     this->solveLeastSquare<dispatch>(data_mesh, data_atom,
                                      this->evalOutput("meshList"));
     return;
   }
 
   /* do communication */
   this->commPoint2Continuum(data_atom);
 
   if (this->is_in_continuum()) {
     this->solveLeastSquare<dispatch>(data_mesh, data_atom,
                                      this->getOutput("meshList"));
   }
 }
 
 /* -------------------------------------------------------------------------- */
 
 void BridgingAtomicContinuum::leastSquareAtomicDOFs(
     ContainerArray<Real> &data_mesh, FieldType field) {
 
   LM_FATAL("to adapt");
 
   if (comm_group_atomic == comm_group_continuum) {
     ComputeExtract extracted_field("ComputeExtract:" + this->getID());
     extracted_field.setParam("FIELD", field);
     extracted_field.compute(this->pointList);
     this->solveLeastSquare<dispatch>(
         data_mesh, extracted_field.evalArrayOutput(), this->meshList);
     return;
   }
 
   ComputeExtract extracted_field("ComputeExtract:" + this->getID());
   extracted_field.setParam("FIELD", field);
   if (this->is_in_atomic())
     extracted_field.compute(this->pointList);
 
   LM_TOIMPLEMENT;
   // extracted_field.resize(Parent::local_points * Dim);
 
   this->leastSquareAtomicData(data_mesh, extracted_field.evalArrayOutput());
 }
 
 /* -------------------------------------------------------------------------- */
 
 void BridgingAtomicContinuum::buildAtomicDOFsNoiseVector(std::vector<Real> &,
                                                          FieldType field) {
 
   ComputeExtract extracted_field("ComputeExtract:" + this->getID());
   extracted_field.setParam("FIELD", field);
   if (this->is_in_atomic())
     extracted_field.compute(this->pointList);
 
   if (this->is_in_continuum()) {
 
     LM_TOIMPLEMENT;
     // auto &field = extracted_field.evalArrayOutput();
     // this->interpolatePointData(field, ??);
     for (UInt i = 0; i < this->local_points * spatial_dimension; ++i)
       LM_TOIMPLEMENT;
     // extracted_field[i] *= -1;
   }
   /* do communication */
   this->synchSumBuffer(extracted_field.evalArrayOutput());
 }
 
 /* -------------------------------------------------------------------------- */
 
 template <typename DomainA, typename DomainC>
 void BridgingAtomicContinuum::checkPositionCoherency(DomainA &domA,
                                                      DomainC &domC) {
 
   LM_TOIMPLEMENT;
 
   // constexpr UInt Dim = DomainC::ContainerPoints::Dim;
   // if (this->in_group_B) {
   //   // interpolate atomic sites to check everything is ok from this
   //   auto &&field = domC.getField(_position0);
   //   UInt *assoc_tmp = &this->pointToElement[0];
 
   //   for (UInt i = 0; i < this->local_points; ++i) {
   //     Vector<Dim> X;
   //     Vector<Dim> pos = this->positions(i);
   //     X = this->interpolate(i, field, assoc_tmp[i]);
 
   //     for (UInt k = 0; k < Dim; ++k) {
   //       if (X[k] != pos[k])
   //         if (fabs(pos[k] - X[k]) > 1e-5) {
   //           searchAtomInLocalPool(
   //               static_cast<typename DomainA::ContainerSubset &>(
   //                   this->pointList),
   //               pos);
   //           DUMP("mismatch in positions (X), atom "
   //                    << i << " dist is " << pos[k] - X[k]
   //                    << " : probably a redistribution trouble check "
   //                       "migrations\n"
   //                    << "computed position is " << X[0] << " " << X[1] << " "
   //                    << X[2] << " position was " << pos[0] << " " << pos[1]
   //                    << " " << pos[2],
   //                DBG_MESSAGE);
   //         }
   //     }
   //   }
   // }
 
   // this->distributeVectorB2A("temp_positions", this->positions);
 
   // if (this->in_group_A) {
 
   //   UInt i = 0;
   //   UInt global_flag = 0;
 
   //   for (auto &&at : this->pointList) {
   //     UInt local_flag = 0;
   //     Vector<Dim> pos = VectorView<Dim>(&this->positions[Dim * i]);
   //     Vector<Dim> at_pos = at.position0();
 
   //     for (UInt k = 0; k < Dim; ++k) {
   //       if (pos[k] != at_pos[k])
   //         if (!local_flag && fabs(pos[k] - at_pos[k]) > 1e-5) {
   //           searchAtomInLocalPool(this->pointList, pos);
   //           DUMP("mismatch in positions (X), atom "
   //                    << i << " dist is "
   //                    << this->positions[Dim * i] - at.position0()[0]
   //                    << " : probably a redistribution trouble check
   //                    migrations"
   //                    << std::endl
   //                    << "ref is " << at << "\nand send position is " <<
   //                    pos[0]
   //                    << " " << pos[1] << " " << pos[2],
   //                DBG_MESSAGE);
   //           local_flag = 1;
   //           global_flag = 1;
   //         }
   //     }
   //     ++i;
   //   }
   //   if (global_flag) {
   //     this->getDuoVector().print("buggy-redistrib");
   //     LM_FATAL("abort due to migration problem");
   //   }
   // }
   // DUMP("position coherency OK", DBG_INFO);
 }
 /* -------------------------------------------------------------------------- */
 
 template <typename Cont, typename Vec>
 void BridgingAtomicContinuum::searchAtomInLocalPool(Cont &container, Vec &x) {
   LM_TOIMPLEMENT;
   //  UInt i = 0;
   //   for (auto &&at : container) {
   // #ifdef TRACE_ATOM
   //     auto pos = at.position0();
   // #endif
   //     IF_COORD_EQUALS(pos, x) {
   //       DUMP("actually searched atom is at ref " << at << " bridge index " <<
   //       i,
   //            DBG_MESSAGE);
   //       break;
   //     }
   //     ++i;
   //   }
   //   if (i == container.size())
   //     DUMP("atom " << x[0] << " " << x[1] << " " << x[2] << " "
   //                  << " not found locally : probably has migrated"
   //                  << " or is simply lost !"
   //                  << " NOT GOOD",
   //          DBG_MESSAGE);
 
   //   i = 0;
   //   for (auto &&at : domA.getContainer()) {
   // #ifdef TRACE_ATOM
   //     auto pos = at.position0();
   // #endif
   //     IF_COORD_EQUALS(pos, x) {
   //       DUMP("actually searched atom is at ref " << at << " bridge index " <<
   //       i,
   //            DBG_MESSAGE);
   //       break;
   //     }
   //     ++i;
   //   }
   //   if (i == domA.getContainer().size())
   //     DUMP("atom not found locally : probably has migrated"
   //              << "or is simply lost !"
   //              << " NOT GOOD",
   //          DBG_MESSAGE);
 }
 /* -------------------------------------------------------------------------- */
 
 void BridgingAtomicContinuum::projectAtomicFieldOnMesh(FieldType field_type) {
 
   this->projectAtomicFieldOnMesh(field_type, this->buffer_for_points);
 
   if (is_in_atomic())
     this->setPointField(field_type, this->buffer_for_points);
 }
 /* -------------------------------------------------------------------------- */
 
 void BridgingAtomicContinuum::projectAtomicFieldOnMesh(
     FieldType field_type, ContainerArray<Real> &buffer) {
 
   const UInt Dim = spatial_dimension;
   if (is_in_continuum() && !this->total_points)
     DUMP("Warning : atomic container is empty: "
              << "cannot proceed atomic projection (check geometries ?!) "
              << this->getID(),
          DBG_WARNING);
 
   if (!this->local_points)
     return;
 
   buffer.resize(this->local_points, Dim);
 
   if (is_in_continuum()) {
     ComputeExtract extracted_field("ComputeExtract:" + this->getID());
     extracted_field.setParam("FIELD", field_type);
     extracted_field.compute(this->meshList);
     this->mesh2Point(extracted_field.evalArrayOutput(), buffer);
     buffer.setCommGroup(comm_group_continuum);
   }
 
   this->distributeVectorB2A("correction_fictifs", buffer);
 }
 /* -------------------------------------------------------------------------- */
 
 void BridgingAtomicContinuum::checkPositionCoherency() { LM_TOIMPLEMENT; }
 
 __END_LIBMULTISCALE__
diff --git a/src/coupling/bridging_inline_impl.hh b/src/coupling/bridging_inline_impl.hh
index 8303829..2a5837e 100644
--- a/src/coupling/bridging_inline_impl.hh
+++ b/src/coupling/bridging_inline_impl.hh
@@ -1,502 +1,507 @@
 /**
  * @file   bridging.cc
  *
  * @author Guillaume Anciaux <guillaume.anciaux@epfl.ch>
  *
  * @date   Fri Jul 11 15:47:44 2014
  *
  * @brief  Bridging object between atomistic and finite elements
  *
  * @section LICENSE
  *
  * Copyright INRIA and CEA
  *
  * The LibMultiScale is a C++ parallel framework for the multiscale
  * coupling methods dedicated to material simulations. This framework
  * provides an API which makes it possible to program coupled simulations
  * and integration of already existing codes.
  *
  * This Project was initiated in a collaboration between INRIA Futurs Bordeaux
  * within ScAlApplix team and CEA/DPTA Ile de France.
  * The project is now continued at the Ecole Polytechnique Fédérale de Lausanne
  * within the LSMS/ENAC laboratory.
  *
  * This software is governed by the CeCILL-C license under French law and
  * abiding by the rules of distribution of free software.  You can  use,
  * modify and/ or redistribute the software under the terms of the CeCILL-C
  * license as circulated by CEA, CNRS and INRIA at the following URL
  * "http://www.cecill.info".
  *
  * As a counterpart to the access to the source code and  rights to copy,
  * modify and redistribute granted by the license, users are provided only
  * with a limited warranty  and the software's author,  the holder of the
  * economic rights,  and the successive licensors  have only  limited
  * liability.
  *
  * In this respect, the user's attention is drawn to the risks associated
  * with loading,  using,  modifying and/or developing or reproducing the
  * software by the user in light of its specific status of free software,
  * that may mean  that it is complicated to manipulate,  and  that  also
  * therefore means  that it is reserved for developers  and  experienced
  * professionals having in-depth computer knowledge. Users are therefore
  * encouraged to load and test the software's suitability as regards their
  * requirements in conditions enabling the security of their systems and/or
  * data to be ensured and,  more generally, to use and operate it in the
  * same conditions as regards security.
  *
  * The fact that you are presently reading this means that you have had
  * knowledge of the CeCILL-C license and that you accept its terms.
  *
  */
 
 /* -------------------------------------------------------------------------- */
 #include "bridging.hh"
 #include "compute_extract.hh"
 #include "factory_multiscale.hh"
 #include "filter_geometry.hh"
 #include "geometry_manager.hh"
 #include "lm_common.hh"
 #include "stimulation_field.hh"
 #include "trace_atom.hh"
 /* -------------------------------------------------------------------------- */
 __BEGIN_LIBMULTISCALE__
 
 template <typename ContA, typename ContC>
 void Bridging::init(ContA &contA, ContC &contC) {
 
   auto all_group = Communicator::getCommunicator().getGroup("all");
 
   DofAssociation::init(contA, contC);
   const UInt Dim = spatial_dimension;
 
   contMesh = contC;
 
-  pointList.alloc<typename ContA::ContainerSubset>("pointList-" +
-                                                   this->getID());
-  meshList.alloc<typename ContC::ContainerSubset>("meshList-" + this->getID());
-
-  pointList->acquireContext(contA);
-  meshList->acquireContext(contC);
-  unmatchedPointList.acquireContext(contA);
-  unmatchedMeshList.acquireContext(contC);
+  if (in_group_A()) {
+    pointList.alloc<typename ContA::ContainerSubset>("pointList-" +
+                                                     this->getID());
+    pointList->acquireContext(contA);
+    unmatchedPointList.acquireContext(contA);
+  }
+
+  if (in_group_B()) {
+    meshList.alloc<typename ContC::ContainerSubset>("meshList-" +
+                                                    this->getID());
+    meshList->acquireContext(contC);
+    unmatchedMeshList.acquireContext(contC);
+  }
 
   buffer_for_points.acquireContext(contA);
   buffer_for_nodes.acquireContext(contC);
 
   DUMPBYPROC("selecting DOFs in bridging zone", DBG_INFO_STARTUP, 0);
   if (in_group_A()) {
     this->buildPointList(contA);
     this->buildPositions<dispatch>(unmatchedPointList.evalOutput());
   }
   if (in_group_B())
     this->buildContinuumDOFsList(contC);
 
   DUMP(this->getID() << " : Generating Communication Scheme", DBG_INFO_STARTUP);
   all_group.synchronize();
   DUMP(this->getID() << " : exchange coarse geometries", DBG_MESSAGE);
   if (this->in_group_A()) {
     this->exchangeGeometries<dispatch>(this->unmatchedPointList.evalOutput());
   }
   if (in_group_B()) {
     this->exchangeGeometries<dispatch>(this->unmatchedMeshList.evalOutput());
   }
   all_group.synchronize();
 
   DUMP(this->getID() << " : exchange points positions", DBG_MESSAGE);
   this->exchangePositions(Dim);
   all_group.synchronize();
 
   DUMP(this->getID() << " : build shape matrix", DBG_MESSAGE);
   if (in_group_B()) {
     DUMP(this->getID() << " : build shape matrix (parsing "
                        << this->local_points << " points by position)",
          DBG_INFO);
     this->buildShapeMatrix<dispatch>(this->local_points,
                                      this->unmatchedMeshList.evalOutput());
     this->local_points = this->assoc_found;
     DUMP(this->getID() << " : I will manage " << this->local_points
                        << " points",
          DBG_INFO);
   }
   all_group.synchronize();
 
   DUMP(this->getID() << " : ExchangeAssociation", DBG_MESSAGE);
   ContainerArray<UInt> managed;
   this->exchangeAssociationInformation(managed, pointToElement);
 
   for (auto &&[i, c_w] : enumerate(this->com_with))
     DUMP("second test Do I communicate with " << i << " : " << c_w, DBG_INFO);
 
   all_group.synchronize();
 
   DUMP(this->getID()
            << " : generate duo vector and detect double point assignement",
        DBG_MESSAGE);
   std::vector<std::vector<UInt>> unassociated;
   if (this->in_group_A())
     this->createDuoVectorA("Point", managed, pointToElement, unassociated);
 
   DUMP(this->getID() << " : doing exchange rejected", DBG_MESSAGE);
   this->exchangeRejectedContinuumOwners(unassociated);
 
   all_group.synchronize();
 
   DUMP(this->getID() << " : doing filter rejected", DBG_MESSAGE);
   if (this->in_group_B())
     this->filterRejectedContinuumOwners(unassociated);
 
   all_group.synchronize();
 
   DUMP(this->getID() << " : filtering position & association vector",
        DBG_MESSAGE);
 
   if (this->in_group_A()) {
     filterPointListForUnmatched<dispatch>(pointList);
   }
 
   if (this->in_group_B()) {
     this->filterArray(this->positions);
     this->filterMapping(pointToElement);
     // this->buildNodeShape<dispatch>(this->meshList);
   }
 
   DUMP(this->getID() << " : all done for scheme generation", DBG_MESSAGE);
 
   all_group.synchronize();
 }
 /* -------------------------------------------------------------------------- */
 
 template <typename ContC>
 void Bridging::buildContinuumDOFsList(ContC &contMesh) {
 
   constexpr UInt Dim = ContC::ContainerSubset::Dim;
 
   unmatchedMeshList.setParam("GEOMETRY", this->geomID);
   unmatchedMeshList.compute(contMesh);
 
   auto &unmatched_mesh =
       unmatchedMeshList.evalOutput<typename ContC::ContainerSubset>();
   DUMP("we have found " << unmatched_mesh.getContainerElems().size()
                         << " concerned elements",
        DBG_INFO_STARTUP);
 
   STARTTIMER("Filling spatial-grid");
 
   auto contElems = unmatched_mesh.getContainerElems();
   auto contNodes = unmatched_mesh.getContainerNodes();
 
   std::vector<UInt> nodes;
   Geometry &geom = *GeometryManager::getManager().getGeometry(this->geomID);
   Cube cube = geom.getBoundingBox();
   DUMP("geometry of the grid => \n" << cube, DBG_INFO_STARTUP);
 
   auto &grid =
       this->grid.alloc<SpatialGridElem<UInt, Dim>>(cube, this->grid_division);
 
   UInt nb_elem = 0;
   for (auto &&el : contElems) {
     std::vector<Vector<Dim>> node_coords;
     auto &&nodes = el.globalIndexes();
     UInt nb = nodes.size();
 
     for (UInt i = 0; i < nb; ++i) {
       auto nd = el.getNode(i);
 
 #ifndef LM_OPTIMIZED
       Real mass_node = nd.mass();
       LM_ASSERT(mass_node > 0, "invalid mass" << nodes[i] << " " << mass_node);
 #endif
 
       node_coords.push_back(nd.position0());
     }
 
     grid.addFiniteElement(nb_elem, node_coords);
     ++nb_elem;
   }
   STOPTIMER("Filling spatial-grid");
 
   DUMP("we have found " << contElems.size() << " concerned elements",
        DBG_INFO_STARTUP);
   DUMP("in average " << grid.getAverageEltByBlock() << " elements per block",
        DBG_INFO_STARTUP);
 }
 /* -------------------------------------------------------------------------- */
 
 template <typename ContA> void Bridging::buildPointList(ContA &contPoints) {
 
   unmatchedPointList.setParam("GEOMETRY", this->geomID);
   unmatchedPointList.compute(contPoints);
   this->local_points = unmatchedPointList.size();
 
   if (!this->local_points)
     DUMP("We found no point in the bridging zone", DBG_INFO);
 
   DUMP("We found " << this->local_points << " point in the bridging zone",
        DBG_INFO_STARTUP);
 }
 /* -------------------------------------------------------------------------- */
 
 template <typename ContMesh>
 void Bridging::buildShapeMatrix(UInt nb_points, ContMesh &unmatchedMeshList) {
 
   pointToElement.assign(nb_points, UINT_MAX);
 
   if (unmatchedMeshList.getContainerElems().size() == 0) {
     // need to free the output produced by the component
     DUMP("elem_rec is empty!", DBG_WARNING);
     this->getOutput("grid").reset();
     this->removeOutput("grid");
     return;
   }
 
   constexpr UInt Dim = ContMesh::ContainerSubset::Dim;
   auto &grid = this->grid.get<SpatialGridElem<UInt, Dim> &>();
 
   //****************************************************************
   /* building the association array points <-> elements */
   //****************************************************************
   STARTTIMER("Construction association");
   for (UInt i = 0; i < nb_points; ++i) {
 
 #ifndef TIMER
     if (i % 100000 == 0)
       DUMP("building association: point " << i << "/" << nb_points, DBG_INFO);
 #endif
 
     Vector<Dim> x = this->positions(i);
 
     pointToElement[i] = UINT_MAX;
 
     for (auto &&j : grid.findSet(x)) {
       auto el = unmatchedMeshList.getContainerElems().get(j);
 
       DUMP("is point " << i << " within element " << j << "?", DBG_ALL);
 
       if (el.contains(x)) {
         LM_ASSERT(pointToElement[i] == UINT_MAX,
                   "this should not happen. "
                       << "I found twice the same point while filtering");
         DUMP("associating point " << i << " and element " << j, DBG_ALL);
         pointToElement[i] = j;
         ++assoc_found;
         break;
       }
     }
   }
 
   STOPTIMER("Construction association");
   std::vector<UInt> nb_points_per_element(
       unmatchedMeshList.getContainerElems().size());
 
   /* build number of atoms per element */
   for (UInt i = 0; i < nb_points; ++i) {
     if (pointToElement[i] != UINT_MAX)
       ++nb_points_per_element[pointToElement[i]];
   }
 
   auto &meshList =
       this->getOutput<typename ContMesh::ContainerSubset>("meshList");
   /* filter element&node list for the unassociated nodes&elements */
   filterContainerElems<dispatch>(nb_points_per_element, this->contMesh);
 
   auto &elements = meshList.getContainerElems();
   auto &nodes = meshList.getContainerNodes();
 
   smatrix.resize(nodes.size(), assoc_found);
 
   /* set the indirection (alloc tab) plus the shapes */
   std::vector<Real> shapes;
   UInt atom_index = 0;
 
   for (UInt i = 0; i < nb_points; ++i) {
     if (pointToElement[i] == UINT_MAX)
       continue;
 
     auto &&X = this->positions(i);
     auto el = elements.get(pointToElement[i]);
     el.computeShapes(shapes, X);
     auto &&node_indices = el.getAlteredConnectivity();
 
     IF_TRACED(X, "checking for atom in trouble");
 
     std::vector<UInt> local_nodes(shapes.size());
     for (UInt nd = 0; nd < shapes.size(); ++nd)
       smatrix.insert(node_indices[nd], atom_index) = shapes[nd];
 
     ++atom_index;
   }
 }
 /* -------------------------------------------------------------------------- */
 template <typename ContC> void Bridging::buildLocalPBCPairs(ContC &meshList) {
 
   UInt npairs = pbc_pairs.size();
   for (UInt pair = 0; pair < npairs; ++pair) {
     UInt ind1 = pbc_pairs[pair].first;
     UInt ind2 = pbc_pairs[pair].second;
     UInt i1 = meshList.subIndex2Index(ind1);
     UInt i2 = meshList.subIndex2Index(ind2);
     if (i1 == UINT_MAX || i2 == UINT_MAX)
       continue;
 
     std::pair<UInt, UInt> p((UInt)(i1), (UInt)(i2));
     local_pbc_pairs.push_back(p);
   }
   DUMP("Detected " << local_pbc_pairs.size() << " local pairs", DBG_MESSAGE);
   LM_TOIMPLEMENT;
   // smatrix->alterMatrixIndexesForPBC(local_pbc_pairs);
 }
 /* -------------------------------------------------------------------------- */
 // template <typename ContC> void Bridging::buildNodeShape(ContC &meshList) {
 
 //   if (this->local_points == 0)
 //     return;
 
 //   UInt nb_coupled_nodes = meshList.size();
 //   node_shape.assign(nb_coupled_nodes, 0);
 
 //   LM_ASSERT(smatrix, "shapematrix object was not allocated "
 //                          << " eventhough local atoms were detected");
 //   smatrix->buildNodeShape(node_shape);
 
 //   buildLocalPBCPairs<dispatch>(this->meshList);
 //   cumulPBC(node_shape);
 
 // #ifndef LM_OPTIMIZED
 
 //   for (UInt i = 0; i < nb_coupled_nodes; ++i) {
 //     if (node_shape[i] <= 1e-1) {
 //       DUMP(i << " " << node_shape[i], DBG_MESSAGE);
 //       LM_FATAL("Please check your geometry:"
 //                << " one or more nodes has zero nodal shape values."
 //                << " Changing the FE element size may resolve this issue!"
 //                << std::endl);
 //     }
 //   }
 
 // #endif // LM_OPTIMIZED
 
 //   FilterManager::getManager().addObject(node_shape);
 // }
 /* -------------------------------------------------------------------------- */
 template <typename ContMesh>
 void Bridging::filterContainerElems(std::vector<UInt> &nb_atom_per_element,
                                     ContMesh &contMesh) {
 
   using ContainerSubset = typename ContMesh::ContainerSubset;
   typename ContainerSubset::ContainerElems new_t(this->getID() + ":elems");
   std::vector<int> new_index;
 
   auto &unmatchedMeshList =
       this->unmatchedMeshList.evalOutput<ContainerSubset>();
   auto &meshList = this->meshList.get<ContainerSubset>();
 
   for (UInt el = 0; el < nb_atom_per_element.size(); ++el) {
     if (nb_atom_per_element[el] > 0) {
 
       DUMP("elem " << el << " becomes " << new_t.size(), DBG_ALL);
       new_index.push_back(new_t.size());
 
       nb_atom_per_element[new_t.size()] = nb_atom_per_element[el];
       new_t.push_back(unmatchedMeshList.getContainerElems().get(el));
     } else
       new_index.push_back(new_t.size());
   }
   nb_atom_per_element.resize(new_t.size());
   meshList.clear();
   // rebuild the element container
   meshList.getContainerElems() = new_t;
   // rebuild the association list
   for (UInt i = 0; i < pointToElement.size(); ++i) {
     if (pointToElement[i] != UINT_MAX) {
       pointToElement[i] = new_index[pointToElement[i]];
     }
   }
 
   meshList.computeAlteredConnectivity(contMesh.getContainerNodes());
   UInt nb = meshList.size();
   if (!nb) {
     DUMP("We found no nodes in bridging zone", DBG_INFO_STARTUP);
     return;
   }
 
   DUMP("We found " << nb << " nodes concerned into "
                    << meshList.getContainerElems().size() << " elements",
        DBG_INFO_STARTUP);
 }
 /* -------------------------------------------------------------------------- */
 template <typename ContA>
 void Bridging::filterPointListForUnmatched(ContA &pointList) {
 
   auto &unmatchedPointList =
       this->unmatchedPointList.evalOutput<typename ContA::ContainerSubset>();
 
   pointList.clear();
 
   for (UInt i = 0; i < pointToElement.size(); ++i)
     if (pointToElement[i] != UINT_MAX) {
       DUMP("for container, atom " << i << " becomes " << pointList.size(),
            DBG_ALL);
       pointList.push_back(unmatchedPointList.get(i));
     } else {
       DUMP("atom filtered " << i << " " << unmatchedPointList.get(i),
            DBG_DETAIL);
     }
   pointList.acquireContext(unmatchedPointList);
 }
 /* -------------------------------------------------------------------------- */
 
 template <typename ContC>
 void Bridging::solveLeastSquare(ContainerArray<Real> &mesh_data,
                                 ContainerArray<Real> &atomic_data,
                                 ContC &meshList) {
 
   // build right hand side of leastsquare system
   mesh_data.resize(meshList.size(), atomic_data.cols());
   mesh_data = smatrix * atomic_data.matrix();
   cumulPBC(mesh_data);
 
   LM_TOIMPLEMENT;
   // // solve least square system
   // for (UInt i = 0; i < meshList.size(); ++i) {
   //   mesh_data(i) /= node_shape[i];
   // }
 }
 /* -------------------------------------------------------------------------- */
 
 // template <typename ContC>
 // void Bridging::averageOnElements(ContainerArray<Real> &data_atomic,
 //                                  ContainerArray<Real> &data_mesh,
 //                                  ContC &meshList [[gnu::unused]]) {
 
 //   LM_TOIMPLEMENT;
 //   //  data_mesh.assign(meshList.getContainerElems().rows(),
 //   //                  meshList.getContainerElems().cols());
 //   // smatrix->averageOnElements(data_atomic, data_mesh);
 // }
 /* -------------------------------------------------------------------------- */
 
 // DECLARE_BRIDGING_ATOMIC_CONTINUUM_TEMPLATE(Bridging)
 // DECLARE_BRIDGING_DD_CONTINUUM_TEMPLATE(Bridging)
 
 // template <typename SparseMatrix>
 // void Bridging::buildLeastSquareMatrix(SparseMatrix &mat) {
 //   mat = smatrix * smatrix.transpose();
 //   cumulPBC(mat);
 // }
 // /* --------------------------------------------------------------------------
 // */
 
 template <typename Matrix> void Bridging::cumulPBC(Matrix &mat) {
 
   for (auto &&[i1, i2] : local_pbc_pairs) {
     mat.row(i2) += mat.row(i1);
   }
 
   for (auto &&[i1, i2] : local_pbc_pairs) {
     mat.row(i1) += mat.row(i2);
   }
 }
 
 /* -------------------------------------------------------------------------- */
 
 __END_LIBMULTISCALE__
diff --git a/src/coupling/kobayashi.cc b/src/coupling/kobayashi.cc
index 29cc80b..489998d 100644
--- a/src/coupling/kobayashi.cc
+++ b/src/coupling/kobayashi.cc
@@ -1,189 +1,189 @@
 /**
  * @file   kobayashi.cc
  *
  * @author Guillaume Anciaux <guillaume.anciaux@epfl.ch>
  *
  * @date   Fri Jul 11 15:47:44 2014
  *
  * @brief  Kobayashi's bridging method
  *
  * @section LICENSE
  *
  * Copyright (©) 2010-2011 EPFL (Ecole Polytechnique Fédérale de Lausanne)
  * Laboratory (LSMS - Laboratoire de Simulation en Mécanique des Solides)
  *
  * LibMultiScale is free  software: you can redistribute it and/or  modify it
  * under the
  * terms  of the  GNU Lesser  General Public  License as  published by  the Free
  * Software Foundation, either version 3 of the License, or (at your option) any
  * later version.
  *
  * LibMultiScale is  distributed in the  hope that it  will be useful, but
  * WITHOUT ANY
  * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
  * A  PARTICULAR PURPOSE. See  the GNU  Lesser General  Public License  for more
  * details.
  *
  * You should  have received  a copy  of the GNU  Lesser General  Public License
  * along with LibMultiScale. If not, see <http://www.gnu.org/licenses/>.
  *
  */
 
 /* -------------------------------------------------------------------------- */
 #include "kobayashi.hh"
 #include "arlequin_template.hh"
 #include "lm_common.hh"
 /* -------------------------------------------------------------------------- */
 
 __BEGIN_LIBMULTISCALE__
 
 /* -------------------------------------------------------------------------- */
 Kobayashi::Kobayashi(const std::string &name)
     : LMObject(name), ArlequinTemplate(name) {
 
   // naming the bridging zones
   std::stringstream fname;
   fname << name << "-bridging";
 }
 /* -------------------------------------------------------------------------- */
 Kobayashi::~Kobayashi() {}
 
 /* -------------------------------------------------------------------------- */
 
 template <typename DomainA, typename DomainC>
 void Kobayashi::init(DomainA &domA, DomainC &domC) {
   if (lm_world_size > 1)
     LM_FATAL("this coupler works only in sequential");
   std::stringstream fname;
 
   // initialize the bridging_zone object
   bridging_zone.init(domA, domC);
 
   // build weights
-  this->computeWeights<dispatch>(this->bridging_zone.pointList,
-                                 this->bridging_zone.meshList);
+  this->computeAtomicWeights<dispatch>(this->bridging_zone.pointList);
+  this->computeContinuumWeights<dispatch>(this->bridging_zone.meshList);
 
   DUMP("Computing initial least square constraint", DBG_INFO);
   buildCGMatrix();
 
   // treat now MD boundary zone
   boundary_zone.init(domA, domC);
 
   DUMP("Init ... done", DBG_INFO_STARTUP);
 }
 
 /* -------------------------------------------------------------------------- */
 
 template <typename DomainA, typename DomainC>
 void Kobayashi::coupling(CouplingStage stage, DomainA &domA [[gnu::unused]],
                          DomainC &domC [[gnu::unused]]) {
 
   if (stage != COUPLING_STEP4)
     return;
 
   boundary_zone.projectAtomicFieldOnMesh(_velocity);
   boundary_zone.projectAtomicFieldOnMesh(_displacement);
 
   correctContinuum(_velocity);
   correctContinuum(_displacement);
   correctAtoms(_velocity);
   correctAtoms(_displacement);
 }
 
 /* -------------------------------------------------------------------------- */
 
 void Kobayashi::buildCGMatrix() {
 
   auto &smatrix = bridging_zone.smatrix;
   this->A = smatrix * smatrix.transpose();
   this->solver.compute(this->A);
 }
 
 /* -------------------------------------------------------------------------- */
 
 ContainerArray<Real> &Kobayashi::buildLeastSquareField(FieldType field_type) {
   auto &smatrix = bridging_zone.smatrix;
   ComputeExtract field(this->getID());
   field.setParam("FIELD", field_type);
   field.compute(this->bridging_zone.pointList);
   Eigen::VectorXd rhs = smatrix * field.evalArrayOutput().matrix();
   Eigen::VectorXd x = this->solver.solve(rhs.matrix());
   auto &ls_field = this->bridging_zone.buffer_for_nodes;
   ls_field.resize(x.rows(), x.cols());
   ls_field = x;
   return ls_field;
 }
 
 /* -------------------------------------------------------------------------- */
 
 void Kobayashi::correctContinuum(FieldType field_type) {
 
   auto &LS_field = this->buildLeastSquareField(field_type);
   auto &weight_mesh = this->weight_mesh.evalArrayOutput();
 
   ComputeExtract field(this->getID());
   field.setParam("FIELD", field_type);
   field.compute(this->bridging_zone.meshList);
 
   for (auto &&[w, ls_f, f] : zip(weight_mesh, LS_field.rowwise(),
                                  field.evalArrayOutput().rowwise())) {
     if (w <= .5) {
       Real speed_projection = this->quality;
       if (w <= 1e-2)
         speed_projection = 1;
       ls_f = speed_projection * (ls_f - f);
     }
   }
   this->bridging_zone.addMeshField(field_type, LS_field);
 }
 /* -------------------------------------------------------------------------- */
 
 void Kobayashi::correctAtoms(FieldType field_type) {
 
   ContainerArray<Real> LS_field;
   bridging_zone.projectAtomicFieldOnMesh(field_type, LS_field);
   auto &weightMD = this->weight_point.evalArrayOutput();
 
   ComputeExtract field(this->getID());
   field.setParam("FIELD", field_type);
   field.compute(this->bridging_zone.pointList);
 
   for (auto &&[w, ls_f, f] :
        zip(weightMD, LS_field.rowwise(), field.evalArrayOutput().rowwise())) {
     if (w <= .5) {
       Real speed_projection = this->quality;
       if (w <= 1e-2)
         speed_projection = 1;
       ls_f = speed_projection * (ls_f - f);
     }
   }
   this->bridging_zone.addPointField(field_type, LS_field);
 }
 /* -------------------------------------------------------------------------- */
 
 /* LMDESC KOBAYASHI
    This keyword is used to set a coupling method
    which will implement the method of Kobayashi and co-workers
    *A simple dynamical scale-coupling method for concurrent simulation of
    hybridized atomistic/coarse-grained-particle system,*
    **Ryo Kobayashi, Takahide Nakamura, Shuji Ogata**,
    *International Journal for Numerical Methods in Engineering Volume 83,
    Issue 2, pages 249-268, 9 July 2010.*
 
    This coupling component works only in 1D and in sequential.
 */
 
 /* LMHERITANCE arlequin_template */
 
 /* LMEXAMPLE
    COUPLING_CODE md fe KOBAYASHI GEOMETRY 3 BOUNDARY 4 GRID_DIVISIONX 10 QUALITY
    1e-3 VERBOSE
  */
 
 void Kobayashi::declareParams() { ArlequinTemplate::declareParams(); }
 /* -------------------------------------------------------------------------- */
 
 DECLARE_COUPLER_INIT_MAKE_CALL(Kobayashi, domA, domC)
 DECLARE_COUPLING_MAKE_CALL(Kobayashi, domA, domC)
 
 __END_LIBMULTISCALE__
diff --git a/src/coupling/xiao.cc b/src/coupling/xiao.cc
index e50ca16..a823ba7 100644
--- a/src/coupling/xiao.cc
+++ b/src/coupling/xiao.cc
@@ -1,348 +1,352 @@
 /**
  * @file   xiao.cc
  *
  * @author Guillaume Anciaux <guillaume.anciaux@epfl.ch>
  *
  * @date   Wed Jan 15 17:00:43 2014
  *
  * @brief  Bridging Domain/Arlequin method
  *
  * @section LICENSE
  *
  * Copyright INRIA and CEA
  *
  * The LibMultiScale is a C++ parallel framework for the multiscale
  * coupling methods dedicated to material simulations. This framework
  * provides an API which makes it possible to program coupled simulations
  * and integration of already existing codes.
  *
  * This Project was initiated in a collaboration between INRIA Futurs Bordeaux
  * within ScAlApplix team and CEA/DPTA Ile de France.
  * The project is now continued at the Ecole Polytechnique Fédérale de Lausanne
  * within the LSMS/ENAC laboratory.
  *
  * This software is governed by the CeCILL-C license under French law and
  * abiding by the rules of distribution of free software.  You can  use,
  * modify and/ or redistribute the software under the terms of the CeCILL-C
  * license as circulated by CEA, CNRS and INRIA at the following URL
  * "http://www.cecill.info".
  *
  * As a counterpart to the access to the source code and  rights to copy,
  * modify and redistribute granted by the license, users are provided only
  * with a limited warranty  and the software's author,  the holder of the
  * economic rights,  and the successive licensors  have only  limited
  * liability.
  *
  * In this respect, the user's attention is drawn to the risks associated
  * with loading,  using,  modifying and/or developing or reproducing the
  * software by the user in light of its specific status of free software,
  * that may mean  that it is complicated to manipulate,  and  that  also
  * therefore means  that it is reserved for developers  and  experienced
  * professionals having in-depth computer knowledge. Users are therefore
  * encouraged to load and test the software's suitability as regards their
  * requirements in conditions enabling the security of their systems and/or
  * data to be ensured and,  more generally, to use and operate it in the
  * same conditions as regards security.
  *
  * The fact that you are presently reading this means that you have had
  * knowledge of the CeCILL-C license and that you accept its terms.
  *
  */
 
 #define TIMER
 /* -------------------------------------------------------------------------- */
 
 #include "xiao.hh"
 #include "lm_common.hh"
 #include "stimulation_zero.hh"
 /* -------------------------------------------------------------------------- */
 __BEGIN_LIBMULTISCALE__
 
 /* -------------------------------------------------------------------------- */
 
 Xiao::Xiao(const std::string &name) : LMObject(name), ArlequinTemplate(name) {
   this->createOutput("unmatched-point-boundary");
   this->createOutput("unmatched-point-bridging");
   this->createOutput("unmatched-mesh-boundary");
   this->createOutput("unmatched-mesh-bridging");
   this->createOutput("matched-point-boundary");
   this->createOutput("matched-point-bridging");
   this->createOutput("matched-mesh-boundary");
   this->createOutput("matched-mesh-bridging");
   this->createOutput("rhs");
   this->createOutput("A");
 }
 
 /* -------------------------------------------------------------------------- */
 
 Xiao::~Xiao() {}
 
 /* -------------------------------------------------------------------------- */
 
 void Xiao::coupling(CouplingStage stage) {
 
   if (!this->is_in_continuum() && !this->is_in_atomic())
     return;
 
   if (stage == COUPLING_STEP2) {
     DUMP("Zero boundary condition", DBG_INFO);
     STARTTIMER("ZERO_BC");
     boundary_zone.setPointField(_force, 0., spatial_dimension);
     STOPTIMER("ZERO_BC");
   }
 
   if (stage != COUPLING_STEP3)
     return;
 
   STARTTIMER("BuildRHS");
   DUMP("Build RHS", DBG_INFO);
   this->buildRHS(_velocity);
   STOPTIMER("BuildRHS");
 
   DUMP("Synch with migration bridging", DBG_INFO);
   STARTTIMER("updatesForMigrations");
   bridging_zone.updateForMigration();
   // this->size_constraint = bridging_zone.getNumberLocalMatchedPoints();
   DUMP("Synch with migration boundary", DBG_INFO);
   boundary_zone.updateForMigration();
   STOPTIMER("updatesForMigrations");
 
   DUMP("Correcting surface effect", DBG_INFO);
   STARTTIMER("projectAtomicVelocitiesOnMe.hh");
   // Parent::MDboundary_zone.projectAtomicDOFsOnMesh(_displacement);
   boundary_zone.projectAtomicFieldOnMesh(_velocity);
   STOPTIMER("projectAtomicVelocitiesOnMe.hh");
 
   STARTTIMER("BuildRHS");
   DUMP("Build RHS", DBG_INFO);
   this->buildRHS(_velocity);
   STOPTIMER("BuildRHS");
 
   DUMP("solving constraint", DBG_INFO);
   STARTTIMER("Solving constraint");
   this->solveConstraint();
   STOPTIMER("Solving constraint");
 
   DUMP("Applying constraint", DBG_INFO);
   STARTTIMER("Correcting");
   this->applyCorrection(_velocity);
   STOPTIMER("Correcting");
 
   DUMP(this->getID() << " : coupling stage all done", DBG_INFO);
 }
 
 /* -------------------------------------------------------------------------- */
 void Xiao::solveConstraint() {
   for (auto &&[r, a] : zip(rhs.rowwise(), A)) {
     r /= a;
   }
 }
 /* -------------------------------------------------------------------------- */
 
 void Xiao::applyCorrection(FieldType field) {
   if (this->is_in_continuum()) {
 
     auto &correction = this->bridging_zone.buffer_for_nodes;
     correction.resize(rhs.rows(), rhs.cols());
 
     correction = -(this->bridging_zone.smatrix * this->rhs.matrix()).array();
     for (auto &&[corr, lbda] : zip(correction.rowwise(), this->lambdas_mesh)) {
       corr /= lbda;
     }
     this->bridging_zone.addMeshField(field, correction);
   }
   if (this->is_in_atomic()) {
     auto &correction = this->bridging_zone.buffer_for_points;
     correction.resize(rhs.rows(), rhs.cols());
     for (auto &&[cor, r, lbda] :
          zip(correction.rowwise(), rhs.rowwise(), lambdas_point)) {
       LM_ASSERT(lbda, "weight associated with atom is zero : abort");
       cor = r / lbda;
     }
     this->bridging_zone.addPointField(field, correction);
   }
 }
 /* -------------------------------------------------------------------------- */
 
 void Xiao::buildRHS(FieldType field_type) {
 
   DUMP("Clean RHS", DBG_INFO);
   if (this->rhs.rows() == 0)
     this->rhs.resize(0, spatial_dimension);
   this->rhs.setZero();
 
   if (this->is_in_continuum()) {
     this->bridging_zone.mesh2Point(field_type, this->rhs);
   }
   if (this->is_in_atomic()) {
 
     ComputeExtract field(this->getID());
     field.setParam("FIELD", field_type);
     field.compute(this->bridging_zone.pointList);
     if (not this->is_in_continuum()) {
       this->rhs = field.evalArrayOutput().array();
     } else {
       this->rhs -= field.evalArrayOutput().array();
     }
   }
   bridging_zone.synchronizeVectorBySum("rhs", this->rhs);
 }
 /* -------------------------------------------------------------------------- */
 
 template <typename DomainA, typename DomainC>
 void Xiao::init(DomainA &domA, DomainC &domC) {
 
   ArlequinTemplate::init(domA, domC);
 
   // allocate the bridging zone (parallel version)
   bridging_zone.setParam("GEOMETRY", this->bridging_geom);
   bridging_zone.setParam("CHECK_COHERENCY", this->check_coherency);
   bridging_zone.setParam("CENTROID", this->centroid_flag);
 
   // set the pbc pairs
   bridging_zone.setPBCPairs(domC.getPBCpairs());
   // initialize the bridging_zone object
   bridging_zone.init(domA, domC);
   // allocate the vectors necessary to continue
-  if (this->is_in_atomic() or bridging_zone.getNumberLocalMatchedPoints()) {
+  if (this->is_in_atomic() // or bridging_zone.getNumberLocalMatchedPoints()
+  ) {
     this->bridging_zone.attachVector(A);
     // this->allocate(bridging_zone.getNumberLocalMatchedPoints());
   }
 
   // build weights
-  this->computeWeights<dispatch>(bridging_zone.pointList,
-                                 bridging_zone.meshList);
+  if (this->is_in_atomic())
+    this->computeAtomicWeights<dispatch>(bridging_zone.pointList);
+
+  if (this->is_in_continuum())
+    this->computeContinuumWeights<dispatch>(bridging_zone.meshList);
 
   /* build constraint matrix */
   this->buildConstraintMatrix();
 
   /* now treat the boundary zone */
   boundary_zone.setParam("GEOMETRY", this->boundary_geom);
   boundary_zone.setParam("CHECK_COHERENCY", this->check_coherency);
   boundary_zone.setParam("CENTROID", this->centroid_flag);
   // initialize the bridging_zone object
   boundary_zone.init(domA, domC);
   //  this->boundary_zone.projectAtomicDOFsOnMesh(_displacement);
   boundary_zone.projectAtomicFieldOnMesh(_velocity);
   boundary_zone.setPointField(_force, 0., spatial_dimension);
 
   this->getOutput("unmatched-point-boundary") =
       boundary_zone.unmatchedPointList;
   this->getOutput("unmatched-point-bridging") =
       bridging_zone.unmatchedPointList;
   this->getOutput("unmatched-mesh-boundary") = boundary_zone.unmatchedMeshList;
   this->getOutput("unmatched-mesh-bridging") = bridging_zone.unmatchedMeshList;
 
   this->getOutput("matched-point-boundary") = boundary_zone.pointList;
   this->getOutput("matched-point-bridging") = bridging_zone.pointList;
   this->getOutput("matched-mesh-boundary") = boundary_zone.meshList;
   this->getOutput("matched-mesh-bridging") = bridging_zone.meshList;
   this->getOutput("rhs") = rhs;
   this->getOutput("A") = A;
 }
 
 /* -------------------------------------------------------------------------- */
 
 void Xiao::buildConstraintMatrix() {
   if (this->is_in_continuum()) {
     auto &shp = this->bridging_zone.smatrix;
     Array lumped_shape(shp.rows(), 1);
     for (UInt i = 0; i < shp.rows(); ++i) {
       lumped_shape(i) = shp.row(i).sum();
     }
     A = (shp.transpose() * (1. / lambdas_mesh * lumped_shape).matrix());
   }
   if (this->is_in_atomic()) {
     if (not this->is_in_continuum())
       A = Array::Zero(lambdas_point.rows(), lambdas_point.cols());
 
     A += 1. / lambdas_point;
   }
   /* synch constraint matrix */
   bridging_zone.synchronizeVectorBySum("A", this->A);
 }
 /* -------------------------------------------------------------------------- */
 
 /* LMDESC XIAO
    This class implements the BridgingDomain/Arlequin method.
    Two zones are declared, one for the coupling (light blue atoms)
    one for providing a stiff boundary condition to the atoms (purple atoms).
    It defines a coupling area as depicted below:
 
    .. image:: images/bridging-zone-BM.svg
 
    In the bridging part a linear weight function is built the weight the
    energies in the Arlequin method flavor.
    The detailed algorithm is:
 
    .. math::
 
      \left\{
      \begin{array}{l}
      \displaystyle\hat{M}_I \ddot{\mathbf{u}}_I = - \mathbf{f}^R_I +
      \sum_{k=1}^L \mathbf{\lambda}_k
      \frac{\partial \mathbf{g}_k}{\partial \mathbf{u}_I} \\
      \displaystyle \hat{m}_i \ddot{\mathbf{d}}_i = \mathbf{f}^R_i + \sum_{k=1}^L
      \mathbf{\lambda}_k
      \frac{\partial \mathbf{g}_k}{\partial \mathbf{d}_i}
      \end{array}
      \right.
 
    where :math:`\alpha(X_I)` and :math:`\alpha(X_i)` are the weight associated
    with nodes and atoms respectively, where
    :math:`\hat{M}_I=\alpha(X_I)M_I` and :math:`\hat{m}_i=(1-\alpha(X_i))m_i`
    and where the constraint multipliers are computed by solving
    :math:`H \Lambda = \mathbf{g}^\star` with:
 
    .. math::
      H_{ik} = \Delta t \left( \sum_J \varphi_J(\mathbf{X}_I) \hat{M_J}^{-1}
      \frac{\partial \mathbf{g}_k}{\partial \mathbf{u}_J} -
      \hat{m}_I^{-1}  \frac{\partial \mathbf{g}_k}{\partial \mathbf{d}_i}
      \right),
 
      \mathbf{g}_i^\star = \sum_J \varphi_J(\mathbf{X}_I)
      \dot{\mathbf{u}}_J^\star
      - \dot{\mathbf{d}}_i^\star,
 
    where :math:`u^\star, d^\star` are the  displacement obtained after one time
    step
    by the integration scheme when the constraints are not applied.
 
    For debugging puposes several computes are registered to the central
    system:
 
    - weight-fe-\${couplerID} : it is a compute containing the weights
      associated with nodes
      inside of the bridging zone (the :math:`\alpha(X_I)`).
    - weight-md-\${couplerID} : it is a compute containing the weights
      associated with atoms
      inside of the bridging zone (the :math:`\alpha(X_i)`).
    - lambdas-fe-\${couplerID} : it is a compute containing the
      :math:`\hat{M}_I`.
    - lambdas-md-\${couplerID} : it is a compute
      containing the :math:`\hat{m}_i`.
 */
 
 /* LMEXAMPLE
    COUPLING_CODE bdmID md fe XIAO GEOMETRY 3 BOUNDARY 4 GRID_DIVISIONX
    10 GRID_DIVISIONY 10 QUALITY 1e-3
 */
 
 /* LMHERITANCE arlequin_template */
 
 void Xiao::declareParams() {
 
   ArlequinTemplate::declareParams();
 
   /* LMKEYWORD CENTROID
      Set the selection of the bridging zones based on centroid.
   */
   this->parseTag("CENTROID", centroid_flag, false);
 }
 
 /* -------------------------------------------------------------------------- */
 
 DECLARE_COUPLER_INIT_MAKE_CALL(Xiao, domA, domC)
 /* -------------------------------------------------------------------------- */
 
 __END_LIBMULTISCALE__