Salome HOME
Ready to detach trio part.
[tools/medcoupling.git] / src / MEDCoupling / MEDCouplingAMRAttribute.cxx
index a3c652165c00a298007e3237774de2b7f91cc0ec..e5701be79a55d43b0813ea6b02cf70422661c23f 100644 (file)
@@ -138,6 +138,23 @@ void DataArrayDoubleCollection::SynchronizeFineEachOther(int patchId, int ghostL
     }
 }
 
+/*!
+ * This method updates \a p1dac ghost zone parts using \a p2dac (which is really const). \a p2 is in the neighborhood of \a p1 (which size is defined by \a ghostLev).
+ */
+void DataArrayDoubleCollection::SynchronizeGhostZoneOfOneUsingTwo(int ghostLev, const MEDCouplingCartesianAMRPatch *p1, const DataArrayDoubleCollection *p1dac, const MEDCouplingCartesianAMRPatch *p2, const DataArrayDoubleCollection *p2dac)
+{
+  if(!p1 || !p1dac || !p2 || !p2dac)
+    throw INTERP_KERNEL::Exception("DataArrayDoubleCollection::SynchronizeGhostZoneOfOneUsingTwo : input pointer must be not NULL !");
+  std::size_t sz(p1dac->_arrs.size());
+  if(p2dac->_arrs.size()!=sz)
+    throw INTERP_KERNEL::Exception("DataArrayDoubleCollection::SynchronizeGhostZoneOfOneUsingTwo : size of DataArrayDouble Collection must be the same !");
+  for(std::size_t i=0;i<sz;i++)
+    {
+      const DataArrayDouble *zeArrWhichGhostsWillBeUpdated(p1dac->_arrs[i]);
+      MEDCouplingCartesianAMRPatch::UpdateNeighborsOfOneWithTwoMixedLev(ghostLev,p1,p2,const_cast<DataArrayDouble *>(zeArrWhichGhostsWillBeUpdated),p2dac->_arrs[i]);
+    }
+}
+
 void DataArrayDoubleCollection::SynchronizeCoarseToFineOnlyInGhostZone(int ghostLev, const MEDCouplingCartesianAMRMeshGen *fatherOfFineMesh, int patchId, const DataArrayDoubleCollection *coarse, DataArrayDoubleCollection *fine)
 {
   if(!fine || !coarse)
@@ -149,6 +166,26 @@ void DataArrayDoubleCollection::SynchronizeCoarseToFineOnlyInGhostZone(int ghost
     fatherOfFineMesh->fillCellFieldOnPatchOnlyOnGhostZone(patchId,coarse->_arrs[i],fine->_arrs[i],ghostLev);
 }
 
+void DataArrayDoubleCollection::synchronizeMyGhostZoneUsing(int ghostLev, const DataArrayDoubleCollection& other, const MEDCouplingCartesianAMRPatch *thisp, const MEDCouplingCartesianAMRPatch *otherp, const MEDCouplingCartesianAMRMeshGen *father) const
+{
+  DataArrayDoubleCollection *thisNC(const_cast<DataArrayDoubleCollection *>(this));
+  std::size_t sz(_arrs.size());
+  if(other._arrs.size()!=sz)
+    throw INTERP_KERNEL::Exception("DataArrayDoubleCollection::synchronizeMyGhostZoneUsing : sizes of collections must match !");
+  for(std::size_t i=0;i<sz;i++)
+    father->fillCellFieldOnPatchOnlyOnGhostZoneWith(ghostLev,thisp,otherp,thisNC->_arrs[i],other._arrs[i]);
+}
+
+void DataArrayDoubleCollection::synchronizeMyGhostZoneUsingExt(int ghostLev, const DataArrayDoubleCollection& other, const MEDCouplingCartesianAMRPatch *thisp, const MEDCouplingCartesianAMRPatch *otherp) const
+{
+  DataArrayDoubleCollection *thisNC(const_cast<DataArrayDoubleCollection *>(this));
+  std::size_t sz(_arrs.size());
+  if(other._arrs.size()!=sz)
+    throw INTERP_KERNEL::Exception("DataArrayDoubleCollection::synchronizeMyGhostZoneUsingExt : sizes of collections must match !");
+  for(std::size_t i=0;i<sz;i++)
+    MEDCouplingCartesianAMRPatch::UpdateNeighborsOfOneWithTwoExt(ghostLev,thisp,otherp,thisNC->_arrs[i],other._arrs[i]);
+}
+
 DataArrayDoubleCollection::DataArrayDoubleCollection(const std::vector< std::pair<std::string,int> >& fieldNames):_arrs(fieldNames.size())
 {
   std::size_t sz(fieldNames.size());
@@ -250,10 +287,10 @@ bool MEDCouplingGridCollection::presenceOf(const MEDCouplingCartesianAMRMeshGen
   return false;
 }
 
-const DataArrayDoubleCollection& MEDCouplingGridCollection::retrieveFieldsAt(int pos) const
+const DataArrayDoubleCollection& MEDCouplingGridCollection::getFieldsAt(int pos) const
 {
   if(pos<0 || pos>(int)_map_of_dadc.size())
-    throw INTERP_KERNEL::Exception("MEDCouplingGridCollection::retrieveFieldsAt : invalid pos given in input ! Must be in [0,size) !");
+    throw INTERP_KERNEL::Exception("MEDCouplingGridCollection::getFieldsAt : invalid pos given in input ! Must be in [0,size) !");
   return *_map_of_dadc[pos].second;
 }
 
@@ -311,32 +348,76 @@ void MEDCouplingGridCollection::SynchronizeCoarseToFine(int ghostLev, const MEDC
     }
 }
 
-void MEDCouplingGridCollection::synchronizeFineEachOther(int ghostLev) const
+/*!
+ * All the pairs in \a ps must share the same father. If not call synchronizeFineEachOtherExt instead.
+ *
+ * \sa synchronizeFineEachOtherExt
+ */
+void MEDCouplingGridCollection::synchronizeFineEachOther(int ghostLev, const std::vector< std::pair<const MEDCouplingCartesianAMRPatch *,const MEDCouplingCartesianAMRPatch *> >& ps) const
+{
+  for(std::vector< std::pair<const MEDCouplingCartesianAMRPatch *,const MEDCouplingCartesianAMRPatch *> >::const_iterator it=ps.begin();it!=ps.end();it++)
+    {
+      int p1,p2;
+      if(!presenceOf((*it).first->getMesh(),p1))
+        throw INTERP_KERNEL::Exception("MEDCouplingGridCollection::synchronizeFineEachOther : internal error #1 !");
+      if(!presenceOf((*it).second->getMesh(),p2))
+        throw INTERP_KERNEL::Exception("MEDCouplingGridCollection::synchronizeFineEachOther : internal error #2 !");
+      const DataArrayDoubleCollection& col1(getFieldsAt(p1));
+      const DataArrayDoubleCollection& col2(getFieldsAt(p2));
+      col1.synchronizeMyGhostZoneUsing(ghostLev,col2,(*it).first,(*it).second,(*it).first->getMesh()->getFather());
+    }
+}
+
+/*!
+ * This method is a generalization of synchronizeFineEachOther because elements in pairs are \b not sharing the same father but are neighbors nevertheless.
+ *
+ * \sa synchronizeFineEachOther
+ */
+void MEDCouplingGridCollection::synchronizeFineEachOtherExt(int ghostLev, const std::vector< std::pair<const MEDCouplingCartesianAMRPatch *,const MEDCouplingCartesianAMRPatch *> >& ps) const
 {
-  std::map<const MEDCouplingCartesianAMRMeshGen *,std::vector< std::pair<const MEDCouplingCartesianAMRMeshGen *, const DataArrayDoubleCollection *> > > m;
+  for(std::vector< std::pair<const MEDCouplingCartesianAMRPatch *,const MEDCouplingCartesianAMRPatch *> >::const_iterator it=ps.begin();it!=ps.end();it++)
+    {
+      int p1,p2;
+      if(!presenceOf((*it).first->getMesh(),p1))
+        throw INTERP_KERNEL::Exception("MEDCouplingGridCollection::synchronizeFineEachOtherExt : internal error #1 !");
+      if(!presenceOf((*it).second->getMesh(),p2))
+        throw INTERP_KERNEL::Exception("MEDCouplingGridCollection::synchronizeFineEachOtherExt : internal error #2 !");
+      const DataArrayDoubleCollection& col1(getFieldsAt(p1));
+      const DataArrayDoubleCollection& col2(getFieldsAt(p2));
+      col1.synchronizeMyGhostZoneUsingExt(ghostLev,col2,(*it).first,(*it).second);
+    }
+}
+
+/*!
+ * The pairs returned share the same direct father. The number of returned elements must be even.
+ */
+std::vector< std::pair<const MEDCouplingCartesianAMRPatch *,const MEDCouplingCartesianAMRPatch *> > MEDCouplingGridCollection::findNeighbors(int ghostLev) const
+{
+  std::vector< std::pair<const MEDCouplingCartesianAMRPatch *,const MEDCouplingCartesianAMRPatch *> > ret;
+  std::map<const MEDCouplingCartesianAMRMeshGen *,std::vector< const MEDCouplingCartesianAMRMeshGen * > > m;
   for(std::vector< std::pair<const MEDCouplingCartesianAMRMeshGen *,MEDCouplingAutoRefCountObjectPtr<DataArrayDoubleCollection> > >::const_iterator it=_map_of_dadc.begin();it!=_map_of_dadc.end();it++)
     {
       const MEDCouplingCartesianAMRMeshGen *fineMesh((*it).first);
       const MEDCouplingCartesianAMRMeshGen *fatherOfFineMesh(fineMesh->getFather());
-      m[fatherOfFineMesh].push_back(std::pair<const MEDCouplingCartesianAMRMeshGen *, const DataArrayDoubleCollection *>(fineMesh,(*it).second));
+      m[fatherOfFineMesh].push_back(fineMesh);
     }
-  for(std::map<const MEDCouplingCartesianAMRMeshGen *,std::vector<std::pair<const MEDCouplingCartesianAMRMeshGen *, const DataArrayDoubleCollection *> > >::const_iterator it0=m.begin();it0!=m.end();it0++)
+  for(std::map<const MEDCouplingCartesianAMRMeshGen *,std::vector< const MEDCouplingCartesianAMRMeshGen * > >::const_iterator it0=m.begin();it0!=m.end();it0++)
     {
-      std::size_t sz((*it0).second.size());
-      std::vector<const MEDCouplingCartesianAMRMeshGen *> v0(sz);
-      std::vector<DataArrayDoubleCollection *> v1(sz);
-      for(std::size_t i=0;i<sz;i++)
-        {
-          v0[i]=(*it0).second[i].first;
-          const DataArrayDoubleCollection *tmp((*it0).second[i].second);
-          v1[i]=const_cast<DataArrayDoubleCollection *>(tmp);
-        }
-      for(std::vector<std::pair<const MEDCouplingCartesianAMRMeshGen *, const DataArrayDoubleCollection *> >::const_iterator it1=(*it0).second.begin();it1!=(*it0).second.end();it1++)
+      for(std::vector<const MEDCouplingCartesianAMRMeshGen *>::const_iterator it1=(*it0).second.begin();it1!=(*it0).second.end();it1++)
         {
-          int patchId((*it0).first->getPatchIdFromChildMesh((*it1).first));
-          DataArrayDoubleCollection::SynchronizeFineEachOther(patchId,ghostLev,(*it0).first,v0,v1);
+          int patchId((*it0).first->getPatchIdFromChildMesh(*it1));
+          std::vector<int> neighs((*it0).first->getPatchIdsInTheNeighborhoodOf(patchId,ghostLev));
+          const MEDCouplingCartesianAMRPatch *pRef((*it0).first->getPatch(patchId));
+          for(std::vector<int>::const_iterator it2=neighs.begin();it2!=neighs.end();it2++)
+            {
+              const MEDCouplingCartesianAMRPatch *pLoc((*it0).first->getPatch(*it2));
+              ret.push_back(std::pair<const MEDCouplingCartesianAMRPatch *,const MEDCouplingCartesianAMRPatch *>(pRef,pLoc));
+            }
         }
     }
+  if(ret.size()%2!=0)
+    throw INTERP_KERNEL::Exception("MEDCouplingGridCollection::findNeighbors : something is wrong ! The number of neighbor pairs must be %2 ==0 !");
+  return ret;
 }
 
 void MEDCouplingGridCollection::SynchronizeCoarseToFineOnlyInGhostZone(int ghostLev, const MEDCouplingGridCollection *coarse, const MEDCouplingGridCollection *fine)
@@ -426,12 +507,12 @@ void MEDCouplingGridCollection::updateTime() const
 /*!
  * This method creates, attach to a main AMR mesh \a gf ( called god father :-) ) and returns a data linked to \a gf ready for the computation.
  */
-MEDCouplingAMRAttribute *MEDCouplingAMRAttribute::New(MEDCouplingCartesianAMRMesh *gf, const std::vector< std::pair<std::string,int> >& fieldNames)
+MEDCouplingAMRAttribute *MEDCouplingAMRAttribute::New(MEDCouplingCartesianAMRMesh *gf, const std::vector< std::pair<std::string,int> >& fieldNames, int ghostLev)
 {
-  return new MEDCouplingAMRAttribute(gf,fieldNames);
+  return new MEDCouplingAMRAttribute(gf,fieldNames,ghostLev);
 }
 
-MEDCouplingAMRAttribute *MEDCouplingAMRAttribute::New(MEDCouplingCartesianAMRMesh *gf, const std::vector< std::pair<std::string, std::vector<std::string> > >& fieldNames)
+MEDCouplingAMRAttribute *MEDCouplingAMRAttribute::New(MEDCouplingCartesianAMRMesh *gf, const std::vector< std::pair<std::string, std::vector<std::string> > >& fieldNames, int ghostLev)
 {
   std::size_t sz(fieldNames.size());
   std::vector< std::pair<std::string,int> > fieldNames2(sz);
@@ -442,7 +523,7 @@ MEDCouplingAMRAttribute *MEDCouplingAMRAttribute::New(MEDCouplingCartesianAMRMes
       fieldNames2[i].second=(int)fieldNames[i].second.size();
       compNames[i]=fieldNames[i].second;
     }
-  MEDCouplingAutoRefCountObjectPtr<MEDCouplingAMRAttribute> ret(New(gf,fieldNames2));
+  MEDCouplingAutoRefCountObjectPtr<MEDCouplingAMRAttribute> ret(New(gf,fieldNames2,ghostLev));
   ret->spillInfoOnComponents(compNames);
   return ret.retn();
 }
@@ -474,7 +555,7 @@ std::vector<DataArrayDouble *> MEDCouplingAMRAttribute::retrieveFieldsOn(MEDCoup
       int tmp(-1);
       if((*it)->presenceOf(mesh,tmp))
         {
-          const DataArrayDoubleCollection& ddc((*it)->retrieveFieldsAt(tmp));
+          const DataArrayDoubleCollection& ddc((*it)->getFieldsAt(tmp));
           return ddc.retrieveFields();
         }
     }
@@ -491,7 +572,7 @@ const DataArrayDouble *MEDCouplingAMRAttribute::getFieldOn(MEDCouplingCartesianA
       int tmp(-1);
       if((*it)->presenceOf(mesh,tmp))
         {
-          const DataArrayDoubleCollection& ddc((*it)->retrieveFieldsAt(tmp));
+          const DataArrayDoubleCollection& ddc((*it)->getFieldsAt(tmp));
           return ddc.getFieldWithName(fieldName);
         }
     }
@@ -504,7 +585,7 @@ const DataArrayDouble *MEDCouplingAMRAttribute::getFieldOn(MEDCouplingCartesianA
  *
  * \return MEDCouplingFieldDouble * - a field on cells that the caller has to deal with (deallocate it).
  */
-MEDCouplingFieldDouble *MEDCouplingAMRAttribute::buildCellFieldOnRecurseWithoutOverlapWithoutGhost(int ghostLev, MEDCouplingCartesianAMRMeshGen *mesh, const std::string& fieldName) const
+MEDCouplingFieldDouble *MEDCouplingAMRAttribute::buildCellFieldOnRecurseWithoutOverlapWithoutGhost(MEDCouplingCartesianAMRMeshGen *mesh, const std::string& fieldName) const
 {
   std::vector<const DataArrayDouble *> recurseArrs;
   std::size_t lev(0);
@@ -513,7 +594,7 @@ MEDCouplingFieldDouble *MEDCouplingAMRAttribute::buildCellFieldOnRecurseWithoutO
       int tmp(-1);
       if((*it)->presenceOf(mesh,tmp))
         {
-          const DataArrayDoubleCollection& ddc((*it)->retrieveFieldsAt(tmp));
+          const DataArrayDoubleCollection& ddc((*it)->getFieldsAt(tmp));
           recurseArrs.push_back(ddc.getFieldWithName(fieldName));
           break;
         }
@@ -524,7 +605,7 @@ MEDCouplingFieldDouble *MEDCouplingAMRAttribute::buildCellFieldOnRecurseWithoutO
       const MEDCouplingGridCollection *gc(_levs[i]);
       gc->fillIfInTheProgenyOf(fieldName,mesh,recurseArrs);
     }
-  return mesh->buildCellFieldOnRecurseWithoutOverlapWithoutGhost(ghostLev,recurseArrs);
+  return mesh->buildCellFieldOnRecurseWithoutOverlapWithoutGhost(_ghost_lev,recurseArrs);
 }
 
 /*!
@@ -534,7 +615,7 @@ MEDCouplingFieldDouble *MEDCouplingAMRAttribute::buildCellFieldOnRecurseWithoutO
  * \return MEDCouplingFieldDouble * - a field on cells that the caller has to deal with (deallocate it).
  *
  */
-MEDCouplingFieldDouble *MEDCouplingAMRAttribute::buildCellFieldOnWithGhost(int ghostLev, MEDCouplingCartesianAMRMeshGen *mesh, const std::string& fieldName) const
+MEDCouplingFieldDouble *MEDCouplingAMRAttribute::buildCellFieldOnWithGhost(MEDCouplingCartesianAMRMeshGen *mesh, const std::string& fieldName) const
 {
   const DataArrayDouble *arr(0);
   for(std::vector< MEDCouplingAutoRefCountObjectPtr<MEDCouplingGridCollection> >::const_iterator it=_levs.begin();it!=_levs.end();it++)
@@ -542,13 +623,13 @@ MEDCouplingFieldDouble *MEDCouplingAMRAttribute::buildCellFieldOnWithGhost(int g
       int tmp(-1);
       if((*it)->presenceOf(mesh,tmp))
         {
-          const DataArrayDoubleCollection& ddc((*it)->retrieveFieldsAt(tmp));
+          const DataArrayDoubleCollection& ddc((*it)->getFieldsAt(tmp));
           arr=ddc.getFieldWithName(fieldName);
         }
     }
   if(!arr)
     throw INTERP_KERNEL::Exception("MEDCouplingAMRAttribute::buildCellFieldOnWithGhost : the mesh specified is not in the progeny of this !");
-  MEDCouplingAutoRefCountObjectPtr<MEDCouplingIMesh> im(mesh->getImageMesh()->buildWithGhost(ghostLev));
+  MEDCouplingAutoRefCountObjectPtr<MEDCouplingIMesh> im(mesh->getImageMesh()->buildWithGhost(_ghost_lev));
   MEDCouplingAutoRefCountObjectPtr<MEDCouplingFieldDouble> ret(MEDCouplingFieldDouble::New(ON_CELLS));
   ret->setMesh(im);
   ret->setArray(const_cast<DataArrayDouble *>(arr));
@@ -560,7 +641,7 @@ MEDCouplingFieldDouble *MEDCouplingAMRAttribute::buildCellFieldOnWithGhost(int g
  * This method synchronizes from fine to coarse direction arrays. This method makes the hypothesis that \a this has been allocated before using
  * MEDCouplingAMRAttribute::alloc method.
  */
-void MEDCouplingAMRAttribute::synchronizeFineToCoarse(int ghostLev)
+void MEDCouplingAMRAttribute::synchronizeFineToCoarse()
 {
   if(_levs.empty())
     throw INTERP_KERNEL::Exception("MEDCouplingAMRAttribute::synchronizeFineToCoarse : not any levels in this !");
@@ -570,15 +651,15 @@ void MEDCouplingAMRAttribute::synchronizeFineToCoarse(int ghostLev)
     {
       sz--;
       const MEDCouplingGridCollection *fine(_levs[sz]),*coarse(_levs[sz-1]);
-      MEDCouplingGridCollection::SynchronizeFineToCoarse(ghostLev,fine,coarse);
+      MEDCouplingGridCollection::SynchronizeFineToCoarse(_ghost_lev,fine,coarse);
     }
 }
 
 /*!
- * This method synchronizes from coarse to fine arrays and fine to fine each other (if ghostLev is >0). This method makes the hypothesis that \a this has been allocated before using
+ * This method synchronizes from coarse to fine arrays and fine to fine each other (if _ghost_lev is >0). This method makes the hypothesis that \a this has been allocated before using
  * MEDCouplingAMRAttribute::alloc method.
  */
-void MEDCouplingAMRAttribute::synchronizeCoarseToFine(int ghostLev)
+void MEDCouplingAMRAttribute::synchronizeCoarseToFine()
 {
   if(_levs.empty())
     throw INTERP_KERNEL::Exception("MEDCouplingAMRAttribute::synchronizeCoarseToFine : not any levels in this !");
@@ -587,61 +668,68 @@ void MEDCouplingAMRAttribute::synchronizeCoarseToFine(int ghostLev)
   for(std::size_t i=1;i<sz;i++)
     {
       const MEDCouplingGridCollection *fine(_levs[i]),*coarse(_levs[i-1]);
-      MEDCouplingGridCollection::SynchronizeCoarseToFine(ghostLev,coarse,fine);
+      MEDCouplingGridCollection::SynchronizeCoarseToFine(_ghost_lev,coarse,fine);
     }
 }
 
 /*!
- * This method performs coarse to fine spread only in the ghost zone.
+ * This method synchronizes the ghost zone of all patches (excepted the god father one).
+ * This method operates in 4 steps. Larger is the number of steps more accurate is the information in the ghost zone.
+ *
+ * - firstly coarse to fine with no interactions between brother patches.
+ * - secondly connected brother patches in a same master patch are updated.
+ * - thirdly connected nephew patches are updated each other.
+ * - forthly nth generation cousin patches are updated each other.
+ *
  * This method makes the hypothesis that \a this has been allocated before using MEDCouplingAMRAttribute::alloc method.
- * So if \a ghostLev == 0 this method has no effect.
+ * So if \a _ghost_lev == 0 this method has no effect.
  */
-void MEDCouplingAMRAttribute::synchronizeCoarseToFineOnlyInGhostZone(int ghostLev)
+void MEDCouplingAMRAttribute::synchronizeAllGhostZones()
 {
   if(_levs.empty())
-    throw INTERP_KERNEL::Exception("MEDCouplingAMRAttribute::synchronizeCoarseToFineOnlyInGhostZone : not any levels in this !");
+    throw INTERP_KERNEL::Exception("MEDCouplingAMRAttribute::synchronizeFineEachOther : not any levels in this !");
+  // 1st - synchronize from coarse to the finest all the patches (excepted the god father one)
   std::size_t sz(_levs.size());
-  //
   for(std::size_t i=1;i<sz;i++)
     {
       const MEDCouplingGridCollection *fine(_levs[i]),*coarse(_levs[i-1]);
-      MEDCouplingGridCollection::SynchronizeCoarseToFineOnlyInGhostZone(ghostLev,coarse,fine);
+      MEDCouplingGridCollection::SynchronizeCoarseToFineOnlyInGhostZone(_ghost_lev,coarse,fine);
     }
-}
-
-/*!
- * This method synchronizes fine each other only in the ghost zone.
- */
-void MEDCouplingAMRAttribute::synchronizeFineEachOtherInGhostZone(int ghostLev)
-{
-  if(_levs.empty())
-    throw INTERP_KERNEL::Exception("MEDCouplingAMRAttribute::synchronizeFineEachOther : not any levels in this !");
-  std::size_t sz(_levs.size());
-  //
+  // 2nd - classical direct sublevel inside common patch
   for(std::size_t i=1;i<sz;i++)
     {
       const MEDCouplingGridCollection *fine(_levs[i]);
       if(!fine)
         throw INTERP_KERNEL::Exception("MEDCouplingAMRAttribute::synchronizeFineEachOtherInGhostZone : presence of a NULL element !");
-      fine->synchronizeFineEachOther(ghostLev);
+      fine->synchronizeFineEachOther(_ghost_lev,_neighbors[i]);
+    }
+  // 3rd - mixed level
+  for(std::vector< std::pair<const MEDCouplingCartesianAMRPatch *,const MEDCouplingCartesianAMRPatch *> >::const_iterator it=_mixed_lev_neighbors.begin();it!=_mixed_lev_neighbors.end();it++)
+    {
+      const DataArrayDoubleCollection *firstDAC(&findCollectionAttachedTo((*it).first->getMesh())),*secondDAC(&findCollectionAttachedTo((*it).second->getMesh()));
+      DataArrayDoubleCollection::SynchronizeGhostZoneOfOneUsingTwo(_ghost_lev,(*it).first,firstDAC,(*it).second,secondDAC);
+    }
+  // 4th - same level but with far ancestor.
+  for(std::size_t i=1;i<sz;i++)
+    {
+      const MEDCouplingGridCollection *fine(_levs[i]);
+      fine->synchronizeFineEachOtherExt(_ghost_lev,_cross_lev_neighbors[i]);
     }
 }
 
 /*!
  * This method allocates all DataArrayDouble instances stored recursively in \a this.
  *
- * \param [in] ghostLev - The size of ghost zone.
- *
  * \sa dealloc
  */
-void MEDCouplingAMRAttribute::alloc(int ghostLev)
+void MEDCouplingAMRAttribute::alloc()
 {
   _tlc.resetState();
   for(std::vector< MEDCouplingAutoRefCountObjectPtr<MEDCouplingGridCollection> >::iterator it=_levs.begin();it!=_levs.end();it++)
     {
       MEDCouplingGridCollection *elt(*it);
       if(elt)
-        elt->alloc(ghostLev);
+        elt->alloc(_ghost_lev);
       else
         throw INTERP_KERNEL::Exception("MEDCouplingAMRAttribute::alloc : internal error !");
     }
@@ -693,7 +781,7 @@ void MEDCouplingAMRAttribute::updateTime() const
 {//tony
 }
 
-MEDCouplingAMRAttribute::MEDCouplingAMRAttribute(MEDCouplingCartesianAMRMesh *gf, const std::vector< std::pair<std::string,int> >& fieldNames):MEDCouplingDataForGodFather(gf)
+MEDCouplingAMRAttribute::MEDCouplingAMRAttribute(MEDCouplingCartesianAMRMesh *gf, const std::vector< std::pair<std::string,int> >& fieldNames, int ghostLev):MEDCouplingDataForGodFather(gf),_ghost_lev(ghostLev)
 {
   //gf non empty, checked by constructor
   int maxLev(gf->getMaxNumberOfLevelsRelativeToThis());
@@ -712,4 +800,48 @@ MEDCouplingAMRAttribute::MEDCouplingAMRAttribute(MEDCouplingCartesianAMRMesh *gf
         }
       _levs[i]=MEDCouplingGridCollection::New(ms,fieldNames);
     }
+  // updates cross levels neighbors
+  _neighbors.resize(_levs.size());
+  _cross_lev_neighbors.resize(_levs.size());
+  if(_levs.empty())
+    throw INTERP_KERNEL::Exception("constructor of MEDCouplingAMRAttribute : not any levels in this !");
+  std::size_t sz(_levs.size());
+  for(std::size_t i=1;i<sz;i++)
+    {
+      const MEDCouplingGridCollection *fine(_levs[i]);
+      if(!fine)
+        throw INTERP_KERNEL::Exception("constructor of MEDCouplingAMRAttribute : presence of a NULL element !");
+      _neighbors[i]=fine->findNeighbors(_ghost_lev);
+      if(i!=sz-1)
+        {
+          for(std::vector< std::pair<const MEDCouplingCartesianAMRPatch *,const MEDCouplingCartesianAMRPatch *> >::const_iterator it=_neighbors[i].begin();it!=_neighbors[i].end();it++)
+            {
+              MEDCouplingCartesianAMRPatch::FindNeighborsOfSubPatchesOf(_ghost_lev,(*it).first,(*it).second,_mixed_lev_neighbors);
+              std::vector< std::vector < std::pair<const MEDCouplingCartesianAMRPatch *,const MEDCouplingCartesianAMRPatch *> > > neighs2(MEDCouplingCartesianAMRPatch::FindNeighborsOfSubPatchesOfSameLev(_ghost_lev,(*it).first,(*it).second));
+              std::size_t fullLev(i+neighs2.size());
+              if(fullLev>=sz)
+                throw INTERP_KERNEL::Exception("constructor of MEDCouplingAMRAttribute : internal error ! something is wrong in computation of cross level neighbors !");
+              std::size_t ii(i+1);
+              for(std::vector< std::vector< std::pair<const MEDCouplingCartesianAMRPatch *,const MEDCouplingCartesianAMRPatch *> > >::const_iterator it0=neighs2.begin();it0!=neighs2.end();it0++,ii++)
+                _cross_lev_neighbors[ii].insert(_cross_lev_neighbors[ii].end(),(*it0).begin(),(*it0).end());
+            }
+        }
+    }
+}
+
+const DataArrayDoubleCollection& MEDCouplingAMRAttribute::findCollectionAttachedTo(const MEDCouplingCartesianAMRMeshGen *m) const
+{
+  for(std::vector< MEDCouplingAutoRefCountObjectPtr<MEDCouplingGridCollection> >::const_iterator it=_levs.begin();it!=_levs.end();it++)
+    {
+      const MEDCouplingGridCollection *elt(*it);
+      if(elt)
+        {
+          int tmp(-1);
+          if(elt->presenceOf(m,tmp))
+            {
+              return elt->getFieldsAt(tmp);
+            }
+        }
+    }
+  throw INTERP_KERNEL::Exception("MEDCouplingAMRAttribute::findCollectionAttachedTo : unable to find such part of mesh in this !");
 }