Salome HOME
Full synchronisation of patches across levels.
[tools/medcoupling.git] / src / MEDCoupling / MEDCouplingCartesianAMRMesh.cxx
index 0960420631fe4c55ff51c3b0db6aa5c6b4496911..ced42519c8b0afb8d42aba209467dcc4d43aa257 100644 (file)
@@ -19,6 +19,7 @@
 // Author : Anthony Geay
 
 #include "MEDCouplingCartesianAMRMesh.hxx"
+#include "MEDCouplingFieldDouble.hxx"
 #include "MEDCoupling1GTUMesh.hxx"
 #include "MEDCouplingIMesh.hxx"
 #include "MEDCouplingUMesh.hxx"
@@ -53,6 +54,22 @@ MEDCouplingCartesianAMRPatchGen::MEDCouplingCartesianAMRPatchGen(MEDCouplingCart
   _mesh=mesh; _mesh->incrRef();
 }
 
+const MEDCouplingCartesianAMRMeshGen *MEDCouplingCartesianAMRPatchGen::getMeshSafe() const
+{
+  const MEDCouplingCartesianAMRMeshGen *mesh(_mesh);
+  if(!mesh)
+    throw INTERP_KERNEL::Exception("MEDCouplingCartesianAMRPatchGen::getMeshSafe const : the mesh is NULL !");
+  return mesh;
+}
+
+MEDCouplingCartesianAMRMeshGen *MEDCouplingCartesianAMRPatchGen::getMeshSafe()
+{
+  MEDCouplingCartesianAMRMeshGen *mesh(_mesh);
+    if(!mesh)
+      throw INTERP_KERNEL::Exception("MEDCouplingCartesianAMRPatchGen::getMeshSafe : the mesh is NULL !");
+    return mesh;
+}
+
 std::vector<const BigMemoryObject *> MEDCouplingCartesianAMRPatchGen::getDirectChildren() const
 {
   std::vector<const BigMemoryObject *> ret;
@@ -73,6 +90,11 @@ MEDCouplingCartesianAMRPatch::MEDCouplingCartesianAMRPatch(MEDCouplingCartesianA
     throw INTERP_KERNEL::Exception("MEDCouplingCartesianAMRPatch constructor : space dimension of father and input bottomLeft/topRight size mismatches !");
 }
 
+void MEDCouplingCartesianAMRPatch::addPatch(const std::vector< std::pair<int,int> >& bottomLeftTopRight, const std::vector<int>& factors)
+{
+  return getMeshSafe()->addPatch(bottomLeftTopRight,factors);
+}
+
 int MEDCouplingCartesianAMRPatch::getNumberOfOverlapedCellsForFather() const
 {
   return MEDCouplingStructuredMesh::DeduceNumberOfGivenRangeInCompactFrmt(_bl_tr);
@@ -80,7 +102,8 @@ int MEDCouplingCartesianAMRPatch::getNumberOfOverlapedCellsForFather() const
 
 /*!
  * This method states if \a other patch is in the neighborhood of \a this. The neighborhood zone is defined by \a ghostLev parameter
- * the must be >= 0.
+ * the must be >= 0. \b WARNING this method only works if \a this and \a other share the same father (no check of this will be done !).
+ * Call isInMyNeighborhoodExt to deal with 2 patches not sharing directly the same father.
  *
  * \param [in] other - The other patch
  * \param [in] ghostLev - The size of the neighborhood zone.
@@ -88,6 +111,8 @@ int MEDCouplingCartesianAMRPatch::getNumberOfOverlapedCellsForFather() const
  * \throw if \a this or \a other are invalid (end before start).
  * \throw if \a ghostLev is \b not >= 0 .
  * \throw if \a this and \a other have not the same space dimension.
+ *
+ * \sa isInMyNeighborhoodExt
  */
 bool MEDCouplingCartesianAMRPatch::isInMyNeighborhood(const MEDCouplingCartesianAMRPatch *other, int ghostLev) const
 {
@@ -97,13 +122,54 @@ bool MEDCouplingCartesianAMRPatch::isInMyNeighborhood(const MEDCouplingCartesian
     throw INTERP_KERNEL::Exception("MEDCouplingCartesianAMRPatch::isInMyNeighborhood : the input patch is NULL !");
   const std::vector< std::pair<int,int> >& thisp(getBLTRRange());
   const std::vector< std::pair<int,int> >& otherp(other->getBLTRRange());
-  std::size_t thispsize(thisp.size());
-  if(thispsize!=otherp.size())
+  return IsInMyNeighborhood(ghostLev,thisp,otherp);
+}
+
+/*!
+ * This method states if \a other patch is in the neighborhood of \a this. The neighborhood zone is defined by \a ghostLev parameter
+ * the must be >= 0. This method works even if \a this and \a other does not share the same father.
+ *
+ * \param [in] other - The other patch
+ * \param [in] ghostLev - The size of the neighborhood zone.
+ *
+ * \throw if \a this or \a other are invalid (end before start).
+ * \throw if \a ghostLev is \b not >= 0 .
+ * \throw if \a this and \a other have not the same space dimension.
+ * \throw if there is not common ancestor of \a this and \a other.
+ *
+ * \sa isInMyNeighborhood
+ */
+bool MEDCouplingCartesianAMRPatch::isInMyNeighborhoodExt(const MEDCouplingCartesianAMRPatch *other, int ghostLev) const
+{
+  if(ghostLev<0)
+    throw INTERP_KERNEL::Exception("MEDCouplingCartesianAMRPatch::isInMyNeighborhoodExt : the size of the neighborhood must be >= 0 !");
+  if(!other)
+    throw INTERP_KERNEL::Exception("MEDCouplingCartesianAMRPatch::isInMyNeighborhoodExt : the input patch is NULL !");
+  int lev;
+  const MEDCouplingCartesianAMRMeshGen *com(FindCommonAncestor(this,other,lev));//check that factors are OK
+  if(lev==0)
+    return isInMyNeighborhood(other,ghostLev);
+  std::vector<int> offset(ComputeOffsetFromTwoToOne(com,lev,this,other));
+  const std::vector< std::pair<int,int> >& thisp(getBLTRRange());
+  std::vector< std::pair<int,int> > otherp(other->getBLTRRange());
+  std::size_t sz(offset.size());
+  for(std::size_t i=0;i<sz;i++)
+    {
+      otherp[i].first+=offset[i];
+      otherp[i].second+=offset[i];
+    }
+  return IsInMyNeighborhood(ghostLev,thisp,otherp);
+}
+
+bool MEDCouplingCartesianAMRPatch::IsInMyNeighborhood(int ghostLev, const std::vector< std::pair<int,int> >& p1, const std::vector< std::pair<int,int> >& p2)
+{
+  std::size_t thispsize(p1.size());
+  if(thispsize!=p2.size())
     throw INTERP_KERNEL::Exception("MEDCouplingCartesianAMRPatch::isInMyNeighborhood : the dimensions must be the same !");
   for(std::size_t i=0;i<thispsize;i++)
     {
-      const std::pair<int,int>& thispp(thisp[i]);
-      const std::pair<int,int>& otherpp(otherp[i]);
+      const std::pair<int,int>& thispp(p1[i]);
+      const std::pair<int,int>& otherpp(p2[i]);
       if(thispp.second<thispp.first)
         throw INTERP_KERNEL::Exception("MEDCouplingCartesianAMRPatch::isInMyNeighborhood : this patch is invalid !");
       if(otherpp.second<otherpp.first)
@@ -119,6 +185,92 @@ bool MEDCouplingCartesianAMRPatch::isInMyNeighborhood(const MEDCouplingCartesian
   return true;
 }
 
+std::vector< std::vector< std::pair<const MEDCouplingCartesianAMRPatch *,const MEDCouplingCartesianAMRPatch *> > > MEDCouplingCartesianAMRPatch::FindNeighborsOfSubPatchesOf(int ghostLev, const MEDCouplingCartesianAMRPatch *p1, const MEDCouplingCartesianAMRPatch *p2)
+{
+  if(!p1 || !p2)
+    throw INTERP_KERNEL::Exception("MEDCouplingCartesianAMRPatch::FindNeighborsOfSubPatchesOf : the input pointers must be not NULL !");
+  std::vector< std::vector< std::pair<const MEDCouplingCartesianAMRPatch *,const MEDCouplingCartesianAMRPatch *> > > ret;
+  std::vector< const MEDCouplingCartesianAMRPatch *> p1Work(p1->getMesh()->getPatches()),p2Work(p2->getMesh()->getPatches());
+  while(!p1Work.empty())
+    {
+      std::vector< std::pair<const MEDCouplingCartesianAMRPatch *,const MEDCouplingCartesianAMRPatch *> > retTmp;
+      std::vector<const MEDCouplingCartesianAMRPatch *> p1Work2,p2Work2;
+      for(std::vector<const MEDCouplingCartesianAMRPatch *>::const_iterator it1=p1Work.begin();it1!=p1Work.end();it1++)
+        {
+          for(std::vector<const MEDCouplingCartesianAMRPatch *>::const_iterator it2=p2Work.begin();it2!=p2Work.end();it2++)
+            {
+              if((*it1)->isInMyNeighborhoodExt(*it2,ghostLev))
+                retTmp.push_back(std::pair<const MEDCouplingCartesianAMRPatch *,const MEDCouplingCartesianAMRPatch *>(*it1,*it2));
+            }
+          std::vector<const MEDCouplingCartesianAMRPatch *> tmp1((*it1)->getMesh()->getPatches());
+          p1Work2.insert(p1Work2.end(),tmp1.begin(),tmp1.end());
+        }
+      for(std::vector<const MEDCouplingCartesianAMRPatch *>::const_iterator it2=p2Work.begin();it2!=p2Work.end();it2++)
+        {
+          std::vector<const MEDCouplingCartesianAMRPatch *> tmp2((*it2)->getMesh()->getPatches());
+          p2Work2.insert(p2Work2.end(),tmp2.begin(),tmp2.end());
+        }
+      ret.push_back(retTmp);
+      p1Work=p1Work2;
+      p2Work=p2Work2;
+    }
+  return ret;
+}
+
+/*!
+ * \a p1 and \a p2 are expected to be neighbors (inside the \a ghostLev zone). This method updates \a dataOnP1 only in the ghost part using a part of \a dataOnP2.
+ *
+ * \saUpdateNeighborsOfOneWithTwoExt
+ */
+void MEDCouplingCartesianAMRPatch::UpdateNeighborsOfOneWithTwo(int ghostLev, const std::vector<int>& factors, const MEDCouplingCartesianAMRPatch *p1, const MEDCouplingCartesianAMRPatch *p2, DataArrayDouble *dataOnP1, const DataArrayDouble *dataOnP2)
+{
+  const std::vector< std::pair<int,int> >& p1BLTR(p1->getBLTRRange());
+  const std::vector< std::pair<int,int> >& p2BLTR(p2->getBLTRRange());
+  UpdateNeighborsOfOneWithTwoInternal(ghostLev,factors,p1BLTR,p2BLTR,dataOnP1,dataOnP2);
+}
+
+void MEDCouplingCartesianAMRPatch::UpdateNeighborsOfOneWithTwoInternal(int ghostLev, const std::vector<int>& factors, const std::vector< std::pair<int,int> >&p1 ,const std::vector< std::pair<int,int> >&p2, DataArrayDouble *dataOnP1, const DataArrayDouble *dataOnP2)
+{//p1=[(1,4),(2,4)] p2=[(4,5),(3,4)]
+  int dim((int)factors.size());
+  std::vector<int> dimsCoarse(MEDCouplingStructuredMesh::GetDimensionsFromCompactFrmt(p1));//[3,2]
+  std::transform(dimsCoarse.begin(),dimsCoarse.end(),factors.begin(),dimsCoarse.begin(),std::multiplies<int>());//[12,8]
+  std::transform(dimsCoarse.begin(),dimsCoarse.end(),dimsCoarse.begin(),std::bind2nd(std::plus<int>(),2*ghostLev));//[14,10]
+  std::vector< std::pair<int,int> > rangeCoarse(MEDCouplingStructuredMesh::GetCompactFrmtFromDimensions(dimsCoarse));//[(0,14),(0,10)]
+  std::vector<int> fakeFactors(dim,1);
+  //
+  std::vector< std::pair<int,int> > tmp0,tmp1,tmp2;
+  MEDCouplingStructuredMesh::ChangeReferenceFromGlobalOfCompactFrmt(p1,p2,tmp0,false);//tmp0=[(3,4),(1,2)]
+  ApplyFactorsOnCompactFrmt(tmp0,factors);//tmp0=[(12,16),(4,8)]
+  ApplyGhostOnCompactFrmt(tmp0,ghostLev);//tmp0=[(13,17),(5,9)]
+  std::vector< std::pair<int,int> > interstRange(MEDCouplingStructuredMesh::IntersectRanges(tmp0,rangeCoarse));//interstRange=[(13,14),(5,9)]
+  MEDCouplingStructuredMesh::ChangeReferenceFromGlobalOfCompactFrmt(p2,p1,tmp1,false);//tmp1=[(-3,0),(-1,1)]
+  ApplyFactorsOnCompactFrmt(tmp1,factors);//tmp1=[(-12,-4),(-4,0)]
+  MEDCouplingStructuredMesh::ChangeReferenceToGlobalOfCompactFrmt(tmp1,interstRange,tmp2,false);//tmp2=[(1,2),(1,5)]
+  //
+  std::vector< std::pair<int,int> > dimsFine(p2);
+  ApplyFactorsOnCompactFrmt(dimsFine,factors);
+  ApplyAllGhostOnCompactFrmt(dimsFine,ghostLev);
+  //
+  MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> ghostVals(MEDCouplingStructuredMesh::ExtractFieldOfDoubleFrom(MEDCouplingStructuredMesh::GetDimensionsFromCompactFrmt(dimsFine),dataOnP2,tmp2));
+  MEDCouplingIMesh::CondenseFineToCoarse(dimsCoarse,ghostVals,interstRange,fakeFactors,dataOnP1);
+}
+
+/*!
+ * Idem than UpdateNeighborsOfOneWithTwo, except that here \a p1 and \a p2 are not sharing the same direct father.
+ *
+ * \sa UpdateNeighborsOfOneWithTwo
+ */
+void MEDCouplingCartesianAMRPatch::UpdateNeighborsOfOneWithTwoExt(int ghostLev, const MEDCouplingCartesianAMRPatch *p1, const MEDCouplingCartesianAMRPatch *p2, DataArrayDouble *dataOnP1, const DataArrayDouble *dataOnP2)
+{
+  const std::vector< std::pair<int,int> >& p1BLTR(p1->getBLTRRange());//p1BLTR=[(10,12),(5,8)]
+  std::vector< std::pair<int,int> > p2BLTR(p2->getBLTRRange());//p2BLTR=[(0,1),(0,5)]
+  int lev(0);
+  const MEDCouplingCartesianAMRMeshGen *ca(FindCommonAncestor(p1,p2,lev));
+  std::vector<int> offset(ComputeOffsetFromTwoToOne(ca,lev,p1,p2));//[12,4]
+  p2BLTR=MEDCouplingStructuredMesh::TranslateCompactFrmt(p2BLTR,offset);//p2BLTR=[(12,13),(4,9)]
+  UpdateNeighborsOfOneWithTwoInternal(ghostLev,p1->getMesh()->getFather()->getFactors(),p1BLTR,p2BLTR,dataOnP1,dataOnP2);
+}
+
 std::size_t MEDCouplingCartesianAMRPatch::getHeapMemorySizeWithoutChildren() const
 {
   std::size_t ret(sizeof(MEDCouplingCartesianAMRPatch));
@@ -126,6 +278,108 @@ std::size_t MEDCouplingCartesianAMRPatch::getHeapMemorySizeWithoutChildren() con
   return ret;
 }
 
+const MEDCouplingCartesianAMRMeshGen *MEDCouplingCartesianAMRPatch::FindCommonAncestor(const MEDCouplingCartesianAMRPatch *p1, const MEDCouplingCartesianAMRPatch *p2, int& lev)
+{
+  const MEDCouplingCartesianAMRMeshGen *f1(p1->_mesh),*f2(p2->_mesh);
+  lev=0;
+  while(f1!=f2 || f1==0 || f2==0)
+    {
+      f1=f1->getFather(); f2=f2->getFather();
+      if(f1->getFactors()!=f2->getFactors())
+        throw INTERP_KERNEL::Exception("MEDCouplingCartesianAMRPatch::FindCommonAncestor : factors differ !");
+      lev++;
+    }
+  if(f1!=f2)
+    throw INTERP_KERNEL::Exception("MEDCouplingCartesianAMRPatch::FindCommonAncestor : no common ancestor between p1 and p2 !");
+  return f1;
+}
+
+std::vector<int> MEDCouplingCartesianAMRPatch::ComputeOffsetFromTwoToOne(const MEDCouplingCartesianAMRMeshGen *comAncestor, int lev, const MEDCouplingCartesianAMRPatch *p1, const MEDCouplingCartesianAMRPatch *p2)
+{
+  if(lev<=0)
+    throw INTERP_KERNEL::Exception("MEDCouplingCartesianAMRPatch::ComputeOffsetFromTwoToOne : this method is useful only for lev > 0 !");
+  int zeLev(lev-1);
+  int dim(p1->getMesh()->getSpaceDimension());
+  if(p2->getMesh()->getSpaceDimension()!=dim)
+    throw INTERP_KERNEL::Exception("MEDCouplingCartesianAMRPatch::ComputeOffsetFromTwoToOne : dimension must be the same !");
+  std::vector< int > ret(dim,0);
+
+  for(int i=0;i<zeLev;i++)
+    {
+      const MEDCouplingCartesianAMRMeshGen *f1(p1->_mesh),*f2(p2->_mesh);
+      const MEDCouplingCartesianAMRPatch *p1h(0),*p2h(0);
+      for(int j=0;j<lev-i;j++)
+        {
+          const MEDCouplingCartesianAMRMeshGen *f1tmp(f1->getFather()),*f2tmp(f2->getFather());
+          int pid1(f1tmp->getPatchIdFromChildMesh(f1)),pid2(f2tmp->getPatchIdFromChildMesh(f2));
+          p1h=f1tmp->getPatch(pid1); p2h=f2tmp->getPatch(pid2);
+          f1=f1tmp; f2=f2tmp;
+        }
+      std::vector< std::pair<int,int> > p2c(p2h->getBLTRRange());
+      for(int k=0;k<dim;k++)
+        {
+          p2c[k].first+=ret[k];
+          p2c[k].second+=ret[k];
+        }
+      for(int k=0;k<dim;k++)
+        {
+          ret[k]=p2c[k].first-p1h->getBLTRRange()[k].first;
+          ret[k]*=f1->getFactors()[k];
+        }
+    }
+  return ret;
+}
+
+/*!
+ * \param [in,out] partBeforeFact - the part of a image mesh in compact format that will be put in refined reference.
+ * \param [in] factors - the factors per axis.
+ */
+void MEDCouplingCartesianAMRPatch::ApplyFactorsOnCompactFrmt(std::vector< std::pair<int,int> >& partBeforeFact, const std::vector<int>& factors)
+{
+  std::size_t sz(factors.size());
+  if(sz!=partBeforeFact.size())
+    throw INTERP_KERNEL::Exception("MEDCouplingCartesianAMRPatch::ApplyFactorsOnCompactFrmt : size of input vectors must be the same !");
+  for(std::size_t i=0;i<sz;i++)
+    {
+      partBeforeFact[i].first*=factors[i];
+      partBeforeFact[i].second*=factors[i];
+    }
+}
+
+/*!
+ * \param [in,out] partBeforeFact - the part of a image mesh in compact format that will be put in ghost reference.
+ * \param [in] ghostSize - the ghost size of zone for all axis.
+ */
+void MEDCouplingCartesianAMRPatch::ApplyGhostOnCompactFrmt(std::vector< std::pair<int,int> >& partBeforeFact, int ghostSize)
+{
+  if(ghostSize<0)
+    throw INTERP_KERNEL::Exception("MEDCouplingCartesianAMRPatch::ApplyGhostOnCompactFrmt : ghost size must be >= 0 !");
+  std::size_t sz(partBeforeFact.size());
+  for(std::size_t i=0;i<sz;i++)
+    {
+      partBeforeFact[i].first+=ghostSize;
+      partBeforeFact[i].second+=ghostSize;
+    }
+}
+
+/*!
+ * This method is different than ApplyGhostOnCompactFrmt. The \a partBeforeFact parameter is enlarger contrary to ApplyGhostOnCompactFrmt.
+ *
+ * \param [in,out] partBeforeFact - the part of a image mesh in compact format that will be put in ghost reference.
+ * \param [in] ghostSize - the ghost size of zone for all axis.
+ */
+void MEDCouplingCartesianAMRPatch::ApplyAllGhostOnCompactFrmt(std::vector< std::pair<int,int> >& partBeforeFact, int ghostSize)
+{
+  if(ghostSize<0)
+    throw INTERP_KERNEL::Exception("MEDCouplingCartesianAMRPatch::ApplyAllGhostOnCompactFrmt : ghost size must be >= 0 !");
+  std::size_t sz(partBeforeFact.size());
+  for(std::size_t i=0;i<sz;i++)
+    {
+      partBeforeFact[i].first-=ghostSize;
+      partBeforeFact[i].second+=ghostSize;
+    }
+}
+
 MEDCouplingCartesianAMRPatchGF::MEDCouplingCartesianAMRPatchGF(MEDCouplingCartesianAMRMesh *mesh):MEDCouplingCartesianAMRPatchGen(mesh)
 {
 }
@@ -135,6 +389,28 @@ std::size_t MEDCouplingCartesianAMRPatchGF::getHeapMemorySizeWithoutChildren() c
   return sizeof(MEDCouplingCartesianAMRPatchGF);
 }
 
+MEDCouplingDataForGodFather::MEDCouplingDataForGodFather(MEDCouplingCartesianAMRMesh *gf):_gf(gf),_tlc(gf)
+{
+  if(!_gf)
+    throw INTERP_KERNEL::Exception("MEDCouplingDataForGodFather constructor : A data has to be attached to a AMR Mesh instance !");
+  _gf->setData(this);
+}
+
+void MEDCouplingDataForGodFather::checkGodFatherFrozen() const
+{
+  _tlc.checkConst();
+}
+
+bool MEDCouplingDataForGodFather::changeGodFather(MEDCouplingCartesianAMRMesh *gf)
+{
+  bool ret(_tlc.keepTrackOfNewTL(gf));
+  if(ret)
+    {
+      _gf=gf;
+    }
+  return ret;
+}
+
 /// @endcond
 
 int MEDCouplingCartesianAMRMeshGen::getSpaceDimension() const
@@ -156,6 +432,7 @@ void MEDCouplingCartesianAMRMeshGen::setFactors(const std::vector<int>& newFacto
   if(!_patches.empty())
     throw INTERP_KERNEL::Exception("MEDCouplingCartesianAMRMeshGen::setFactors : modification of factors is not allowed when presence of patches !");
   _factors=newFactors;
+  declareAsNew();
 }
 
 int MEDCouplingCartesianAMRMeshGen::getMaxNumberOfLevelsRelativeToThis() const
@@ -166,11 +443,33 @@ int MEDCouplingCartesianAMRMeshGen::getMaxNumberOfLevelsRelativeToThis() const
   return ret;
 }
 
+/*!
+ * This method returns the number of cells of \a this with the help of the MEDCouplingIMesh instance representing \a this.
+ * The patches in \a this are ignored here.
+ * \sa getNumberOfCellsAtCurrentLevelGhost, getNumberOfCellsRecursiveWithOverlap
+ */
 int MEDCouplingCartesianAMRMeshGen::getNumberOfCellsAtCurrentLevel() const
 {
   return _mesh->getNumberOfCells();
 }
 
+/*!
+ * This method returns the number of cells of \a this with the help of the MEDCouplingIMesh instance representing \a this enlarged by \a ghostLev size
+ * to take into account of the ghost cells for future computation.
+ * The patches in \a this are ignored here.
+ *
+ * \sa getNumberOfCellsAtCurrentLevel
+ */
+int MEDCouplingCartesianAMRMeshGen::getNumberOfCellsAtCurrentLevelGhost(int ghostLev) const
+{
+  MEDCouplingAutoRefCountObjectPtr<MEDCouplingIMesh> tmp(_mesh->buildWithGhost(ghostLev));
+  return tmp->getNumberOfCells();
+}
+
+/*!
+ * This method returns the number of cells including the current level but \b also \b including recursively all cells of other levels
+ * starting from this. The set of cells which size is returned here are generally overlapping each other.
+ */
 int MEDCouplingCartesianAMRMeshGen::getNumberOfCellsRecursiveWithOverlap() const
 {
   int ret(_mesh->getNumberOfCells());
@@ -181,6 +480,13 @@ int MEDCouplingCartesianAMRMeshGen::getNumberOfCellsRecursiveWithOverlap() const
   return ret;
 }
 
+/*!
+ * This method returns the max number of cells covering all the space without overlapping.
+ * It returns the number of cells of the mesh with the highest resolution.
+ * The returned value is equal to the number of cells of mesh returned by buildUnstructured.
+ *
+ * \sa buildUnstructured
+ */
 int MEDCouplingCartesianAMRMeshGen::getNumberOfCellsRecursiveWithoutOverlap() const
 {
   int ret(_mesh->getNumberOfCells());
@@ -241,6 +547,7 @@ std::vector<MEDCouplingCartesianAMRPatchGen *> MEDCouplingCartesianAMRMeshGen::r
 void MEDCouplingCartesianAMRMeshGen::detachFromFather()
 {
   _father=0;
+  declareAsNew();
 }
 
 /*!
@@ -256,6 +563,7 @@ void MEDCouplingCartesianAMRMeshGen::addPatch(const std::vector< std::pair<int,i
   MEDCouplingAutoRefCountObjectPtr<MEDCouplingCartesianAMRMeshSub> zeMesh(new MEDCouplingCartesianAMRMeshSub(this,mesh));
   MEDCouplingAutoRefCountObjectPtr<MEDCouplingCartesianAMRPatch> elt(new MEDCouplingCartesianAMRPatch(zeMesh,bottomLeftTopRight));
   _patches.push_back(elt);
+  declareAsNew();
 }
 
 /// @cond INTERNAL
@@ -570,6 +878,7 @@ void MEDCouplingCartesianAMRMeshGen::createPatchesFromCriterion(const INTERP_KER
     }
   for(std::vector< MEDCouplingAutoRefCountObjectPtr<InternalPatch> >::const_iterator it=listOfPatchesOK.begin();it!=listOfPatchesOK.end();it++)
     addPatch((*it)->getConstPart(),factors);
+  declareAsNew();
 }
 
 /*!
@@ -581,6 +890,7 @@ void MEDCouplingCartesianAMRMeshGen::createPatchesFromCriterion(const INTERP_KER
     throw INTERP_KERNEL::Exception("MEDCouplingCartesianAMRMesh::createPatchesFromCriterion : the criterion DataArrayByte instance must be allocated and not NULL !");
   std::vector<bool> crit(criterion->toVectorOfBool());//check that criterion has one component.
   createPatchesFromCriterion(bso,crit,factors);
+  declareAsNew();
 }
 
 void MEDCouplingCartesianAMRMeshGen::removeAllPatches()
@@ -607,6 +917,26 @@ int MEDCouplingCartesianAMRMeshGen::getNumberOfPatches() const
   return (int)_patches.size();
 }
 
+int MEDCouplingCartesianAMRMeshGen::getPatchIdFromChildMesh(const MEDCouplingCartesianAMRMeshGen *mesh) const
+{
+  int ret(0);
+  for(std::vector< MEDCouplingAutoRefCountObjectPtr<MEDCouplingCartesianAMRPatch> >::const_iterator it=_patches.begin();it!=_patches.end();it++,ret++)
+    {
+      if((*it)->getMesh()==mesh)
+        return ret;
+    }
+  throw INTERP_KERNEL::Exception("MEDCouplingCartesianAMRMeshGen::getPatchIdFromChildMesh : no such a mesh in my direct progeny !");
+}
+
+std::vector< const MEDCouplingCartesianAMRPatch *> MEDCouplingCartesianAMRMeshGen::getPatches() const
+{
+  std::size_t sz(_patches.size());
+  std::vector< const MEDCouplingCartesianAMRPatch *> ret(sz);
+  for(std::size_t i=0;i<sz;i++)
+    ret[i]=_patches[i];
+  return ret;
+}
+
 const MEDCouplingCartesianAMRPatch *MEDCouplingCartesianAMRMeshGen::getPatch(int patchId) const
 {
   checkPatchId(patchId);
@@ -619,21 +949,8 @@ const MEDCouplingCartesianAMRPatch *MEDCouplingCartesianAMRMeshGen::getPatch(int
  */
 bool MEDCouplingCartesianAMRMeshGen::isPatchInNeighborhoodOf(int patchId1, int patchId2, int ghostLev) const
 {
-  if(ghostLev<0)
-    throw INTERP_KERNEL::Exception("MEDCouplingCartesianAMRMesh::isPatchInNeighborhoodOf : the ghost size must be >=0 !");
   const MEDCouplingCartesianAMRPatch *p1(getPatch(patchId1)),*p2(getPatch(patchId2));
-  if(_factors.empty())
-    throw INTERP_KERNEL::Exception("MEDCouplingCartesianAMRMesh::isPatchInNeighborhoodOf : no factors defined !");
-  int ghostLevInPatchRef;
-  if(ghostLev==0)
-    ghostLevInPatchRef=0;
-  else
-    {
-      ghostLevInPatchRef=(ghostLev-1)/_factors[0]+1;
-      for(std::size_t i=0;i<_factors.size();i++)
-        ghostLevInPatchRef=std::max(ghostLevInPatchRef,(ghostLev-1)/_factors[i]+1);
-    }
-  return p1->isInMyNeighborhood(p2,ghostLevInPatchRef);
+  return p1->isInMyNeighborhood(p2,GetGhostLevelInFineRef(ghostLev,_factors));
 }
 
 /*!
@@ -698,6 +1015,23 @@ void MEDCouplingCartesianAMRMeshGen::fillCellFieldOnPatchGhost(int patchId, cons
   MEDCouplingIMesh::SpreadCoarseToFineGhost(cellFieldOnThis,_mesh->getCellGridStructure(),cellFieldOnPatch,patch->getBLTRRange(),getFactors(),ghostLev);
 }
 
+/*!
+ * This method is equivalent to  fillCellFieldOnPatchGhost except that here \b ONLY \b the \b ghost \b zone will be updated
+ * in \a cellFieldOnPatch.
+ *
+ * \param [in] patchId - The id of the patch \a cellFieldOnThis has to be put on.
+ * \param [in] cellFieldOnThis - The array of the cell field on \c this->getImageMesh() to be projected to patch having id \a patchId.
+ * \param [in,out] cellFieldOnPatch - The array of the cell field on the requested patch to be filled \b only \b in \b the \b ghost \b zone.
+ * \param [in] ghostLev - The size of the ghost zone (must be >=0 !)
+ */
+void MEDCouplingCartesianAMRMeshGen::fillCellFieldOnPatchOnlyOnGhostZone(int patchId, const DataArrayDouble *cellFieldOnThis, DataArrayDouble *cellFieldOnPatch, int ghostLev) const
+{
+  if(!cellFieldOnThis || !cellFieldOnThis->isAllocated())
+    throw INTERP_KERNEL::Exception("MEDCouplingCartesianAMRMesh::fillCellFieldOnPatchOnlyOnGhostZone : the input cell field array is NULL or not allocated !");
+  const MEDCouplingCartesianAMRPatch *patch(getPatch(patchId));
+  MEDCouplingIMesh::SpreadCoarseToFineGhostZone(cellFieldOnThis,_mesh->getCellGridStructure(),cellFieldOnPatch,patch->getBLTRRange(),getFactors(),ghostLev);
+}
+
 /*!
  * This method is a refinement of fillCellFieldOnPatchGhost. fillCellFieldOnPatchGhost is first called.
  * Then for all other patches than those pointed by \a patchId that overlap the ghost zone of the patch impact the ghost zone adequately.
@@ -707,10 +1041,12 @@ void MEDCouplingCartesianAMRMeshGen::fillCellFieldOnPatchGhost(int patchId, cons
  * \param [in,out] cellFieldOnPatch - The array of the cell field on the requested patch to be filled.
  * \param [in] ghostLev - The size of the ghost zone (must be >=0 !)
  * \param [in] arrsOnPatches - \b WARNING arrsOnPatches[patchId] is \b NOT \b const. All others are const.
+ *
+ * \sa fillCellFieldOnPatchOnlyGhostAdv
  */
 void MEDCouplingCartesianAMRMeshGen::fillCellFieldOnPatchGhostAdv(int patchId, const DataArrayDouble *cellFieldOnThis, int ghostLev, const std::vector<const DataArrayDouble *>& arrsOnPatches) const
 {
-  int nbp(getNumberOfPatches()),dim(getSpaceDimension());
+  int nbp(getNumberOfPatches());
   if(nbp!=(int)arrsOnPatches.size())
     {
       std::ostringstream oss; oss << "MEDCouplingCartesianAMRMesh::fillCellFieldOnPatchGhostAdv : there are " << nbp << " patches in this and " << arrsOnPatches.size() << " arrays in the last parameter !";
@@ -719,41 +1055,38 @@ void MEDCouplingCartesianAMRMeshGen::fillCellFieldOnPatchGhostAdv(int patchId, c
   DataArrayDouble *theFieldToFill(const_cast<DataArrayDouble *>(arrsOnPatches[patchId]));
   // first, do as usual
   fillCellFieldOnPatchGhost(patchId,cellFieldOnThis,theFieldToFill,ghostLev);
-  // all reference patch stuff
+  fillCellFieldOnPatchOnlyGhostAdv(patchId,ghostLev,arrsOnPatches);
+}
+
+/*!
+ * This method updates the patch with id \a patchId considering the only the all the patches in \a this to fill ghost zone.
+ * So \b warning, the DataArrayDouble instance \a arrsOnPatches[patchId] is non const.
+ *
+ * \sa getPatchIdsInTheNeighborhoodOf
+ */
+void MEDCouplingCartesianAMRMeshGen::fillCellFieldOnPatchOnlyGhostAdv(int patchId, int ghostLev, const std::vector<const DataArrayDouble *>& arrsOnPatches) const
+{
+  int nbp(getNumberOfPatches());
+  if(nbp!=(int)arrsOnPatches.size())
+    {
+      std::ostringstream oss; oss << "MEDCouplingCartesianAMRMesh::fillCellFieldOnPatchOnlyGhostAdv : there are " << nbp << " patches in this and " << arrsOnPatches.size() << " arrays in the last parameter !";
+      throw INTERP_KERNEL::Exception(oss.str().c_str());
+    }
   const MEDCouplingCartesianAMRPatch *refP(getPatch(patchId));
-  const std::vector< std::pair<int,int> >& refBLTR(refP->getBLTRRange());//[(1,4),(2,4)]
-  std::vector<int> dimsCoarse(MEDCouplingStructuredMesh::GetDimensionsFromCompactFrmt(refBLTR));//[3,2]
-  std::transform(dimsCoarse.begin(),dimsCoarse.end(),_factors.begin(),dimsCoarse.begin(),std::multiplies<int>());//[12,8]
-  std::transform(dimsCoarse.begin(),dimsCoarse.end(),dimsCoarse.begin(),std::bind2nd(std::plus<int>(),2*ghostLev));//[14,10]
-  std::vector< std::pair<int,int> > rangeCoarse(MEDCouplingStructuredMesh::GetCompactFrmtFromDimensions(dimsCoarse));//[(0,14),(0,10)]
-  std::vector<int> fakeFactors(dim,1);
-  //
-  for(int i=0;i<nbp;i++)
+  DataArrayDouble *theFieldToFill(const_cast<DataArrayDouble *>(arrsOnPatches[patchId]));
+  std::vector<int> ids(getPatchIdsInTheNeighborhoodOf(patchId,ghostLev));
+  for(std::vector<int>::const_iterator it=ids.begin();it!=ids.end();it++)
     {
-      if(i!=patchId)
-        if(isPatchInNeighborhoodOf(i,patchId,ghostLev))
-          {
-            const MEDCouplingCartesianAMRPatch *otherP(getPatch(i));
-            const std::vector< std::pair<int,int> >& otherBLTR(otherP->getBLTRRange());//[(4,5),(3,4)]
-            std::vector< std::pair<int,int> > tmp0,tmp1,tmp2;
-            MEDCouplingStructuredMesh::ChangeReferenceFromGlobalOfCompactFrmt(refBLTR,otherBLTR,tmp0,false);//tmp0=[(3,4),(1,2)]
-            ApplyFactorsOnCompactFrmt(tmp0,_factors);//tmp0=[(12,16),(4,8)]
-            ApplyGhostOnCompactFrmt(tmp0,ghostLev);//tmp0=[(13,17),(5,9)]
-            std::vector< std::pair<int,int> > interstRange(MEDCouplingStructuredMesh::IntersectRanges(tmp0,rangeCoarse));//interstRange=[(13,14),(5,9)]
-            MEDCouplingStructuredMesh::ChangeReferenceFromGlobalOfCompactFrmt(otherBLTR,refBLTR,tmp1,false);//tmp1=[(-3,0),(-1,1)]
-            ApplyFactorsOnCompactFrmt(tmp1,_factors);//tmp1=[(-12,-4),(-4,0)]
-            MEDCouplingStructuredMesh::ChangeReferenceToGlobalOfCompactFrmt(tmp1,interstRange,tmp2,false);//tmp2=[(1,2),(1,5)]
-            //
-            std::vector< std::pair<int,int> > dimsFine(otherBLTR);
-            ApplyFactorsOnCompactFrmt(dimsFine,_factors);
-            ApplyAllGhostOnCompactFrmt(dimsFine,ghostLev);
-            //
-            MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> ghostVals(MEDCouplingStructuredMesh::ExtractFieldOfDoubleFrom(MEDCouplingStructuredMesh::GetDimensionsFromCompactFrmt(dimsFine),arrsOnPatches[i],tmp2));
-            MEDCouplingIMesh::CondenseFineToCoarse(dimsCoarse,ghostVals,interstRange,fakeFactors,theFieldToFill);
-          }
+      const MEDCouplingCartesianAMRPatch *otherP(getPatch(*it));
+      MEDCouplingCartesianAMRPatch::UpdateNeighborsOfOneWithTwo(ghostLev,_factors,refP,otherP,theFieldToFill,arrsOnPatches[*it]);
     }
 }
 
+void MEDCouplingCartesianAMRMeshGen::fillCellFieldOnPatchOnlyOnGhostZoneWith(int ghostLev, const MEDCouplingCartesianAMRPatch *patchToBeModified, const MEDCouplingCartesianAMRPatch *neighborPatch, DataArrayDouble *cellFieldOnPatch, const DataArrayDouble *cellFieldNeighbor) const
+{
+  MEDCouplingCartesianAMRPatch::UpdateNeighborsOfOneWithTwo(ghostLev,_factors,patchToBeModified,neighborPatch,cellFieldOnPatch,cellFieldNeighbor);
+}
+
 /*!
  * This method updates \a cellFieldOnThis part of values coming from the cell field \a cellFieldOnPatch lying on patch having id \a patchId.
  *
@@ -874,6 +1207,78 @@ MEDCoupling1SGTUMesh *MEDCouplingCartesianAMRMeshGen::buildMeshOfDirectChildrenO
     return MEDCoupling1SGTUMesh::Merge1SGTUMeshes(patches);
 }
 
+/*!
+ * This method works same as buildUnstructured except that arrays are given in input to build a field on cell in output.
+ * \return MEDCouplingFieldDouble * - a newly created instance the caller has reponsability to deal with.
+ * \sa buildUnstructured
+ */
+MEDCouplingFieldDouble *MEDCouplingCartesianAMRMeshGen::buildCellFieldOnRecurseWithoutOverlapWithoutGhost(int ghostSz, const std::vector<const DataArrayDouble *>& recurseArrs) const
+{
+  if(recurseArrs.empty())
+    throw INTERP_KERNEL::Exception("MEDCouplingCartesianAMRMeshGen::buildCellFieldOnRecurseWithoutOverlapWithoutGhost : array is empty ! Should never happen !");
+  //
+  std::vector<bool> bs(_mesh->getNumberOfCells(),false);
+  std::vector<int> cgs(_mesh->getCellGridStructure());
+  std::vector< MEDCouplingAutoRefCountObjectPtr<MEDCouplingFieldDouble> > msSafe(_patches.size()+1);
+  std::size_t ii(0);
+  for(std::vector< MEDCouplingAutoRefCountObjectPtr<MEDCouplingCartesianAMRPatch> >::const_iterator it=_patches.begin();it!=_patches.end();it++,ii++)
+    {
+      MEDCouplingStructuredMesh::SwitchOnIdsFrom(cgs,(*it)->getBLTRRange(),bs);
+      std::vector<const DataArrayDouble *> tmpArrs(extractSubTreeFromGlobalFlatten((*it)->getMesh(),recurseArrs));
+      msSafe[ii+1]=(*it)->getMesh()->buildCellFieldOnRecurseWithoutOverlapWithoutGhost(ghostSz,tmpArrs);
+    }
+  MEDCouplingAutoRefCountObjectPtr<DataArrayInt> eltsOff(DataArrayInt::BuildListOfSwitchedOff(bs));
+  //
+  MEDCouplingAutoRefCountObjectPtr<MEDCouplingFieldDouble> ret(MEDCouplingFieldDouble::New(ON_CELLS));
+  MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> arr2(extractGhostFrom(ghostSz,recurseArrs[0]));
+  arr2=arr2->selectByTupleIdSafe(eltsOff->begin(),eltsOff->end());
+  ret->setArray(arr2);
+  ret->setName(arr2->getName());
+  MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> part(_mesh->buildUnstructured());
+  MEDCouplingAutoRefCountObjectPtr<MEDCouplingMesh> mesh(part->buildPartOfMySelf(eltsOff->begin(),eltsOff->end(),false));
+  ret->setMesh(mesh);
+  msSafe[0]=ret;
+  //
+  std::vector< const MEDCouplingFieldDouble * > ms(msSafe.size());
+  for(std::size_t i=0;i<msSafe.size();i++)
+    ms[i]=msSafe[i];
+  //
+  return MEDCouplingFieldDouble::MergeFields(ms);
+}
+
+/*!
+ * This method extracts from \arr arr the part inside \a arr by cutting the \a ghostSz external part.
+ * \arr is expected to be an array having a number of tuples equal to \c getImageMesh()->buildWithGhost(ghostSz).
+ */
+DataArrayDouble *MEDCouplingCartesianAMRMeshGen::extractGhostFrom(int ghostSz, const DataArrayDouble *arr) const
+{
+  std::vector<int> st(_mesh->getCellGridStructure());
+  std::vector< std::pair<int,int> > p(MEDCouplingStructuredMesh::GetCompactFrmtFromDimensions(st));
+  std::transform(st.begin(),st.end(),st.begin(),std::bind2nd(std::plus<int>(),2*ghostSz));
+  MEDCouplingCartesianAMRPatch::ApplyGhostOnCompactFrmt(p,ghostSz);
+  MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> ret(MEDCouplingStructuredMesh::ExtractFieldOfDoubleFrom(st,arr,p));
+  return ret.retn();
+}
+
+/*!
+ * This method returns all the patches in \a this not equal to \a patchId that are in neighborhood of patch with id \a patchId.
+ *
+ * \sa fillCellFieldOnPatchOnlyGhostAdv
+ */
+std::vector<int> MEDCouplingCartesianAMRMeshGen::getPatchIdsInTheNeighborhoodOf(int patchId, int ghostLev) const
+{
+  std::vector<int> ret;
+  int nbp(getNumberOfPatches());
+  //
+  for(int i=0;i<nbp;i++)
+    {
+      if(i!=patchId)
+        if(isPatchInNeighborhoodOf(i,patchId,ghostLev))
+          ret.push_back(i);
+    }
+  return ret;
+}
+
 MEDCouplingCartesianAMRMeshGen::MEDCouplingCartesianAMRMeshGen(const std::string& meshName, int spaceDim, const int *nodeStrctStart, const int *nodeStrctStop,
                                                                const double *originStart, const double *originStop, const double *dxyzStart, const double *dxyzStop):_father(0)
 {
@@ -946,54 +1351,54 @@ void MEDCouplingCartesianAMRMeshGen::retrieveGridsAtInternal(int lev, std::vecto
     }
 }
 
-/*!
- * \param [in,out] partBeforeFact - the part of a image mesh in compact format that will be put in refined reference.
- * \param [in] factors - the factors per axis.
- */
-void MEDCouplingCartesianAMRMeshGen::ApplyFactorsOnCompactFrmt(std::vector< std::pair<int,int> >& partBeforeFact, const std::vector<int>& factors)
+int MEDCouplingCartesianAMRMeshGen::GetGhostLevelInFineRef(int ghostLev, const std::vector<int>& factors)
 {
-  std::size_t sz(factors.size());
-  if(sz!=partBeforeFact.size())
-    throw INTERP_KERNEL::Exception("MEDCouplingCartesianAMRMeshGen::ApplyFactorsOnCompactFrmt : size of input vectors must be the same !");
-  for(std::size_t i=0;i<sz;i++)
-    {
-      partBeforeFact[i].first*=factors[i];
-      partBeforeFact[i].second*=factors[i];
-    }
-}
-
-/*!
- * \param [in,out] partBeforeFact - the part of a image mesh in compact format that will be put in ghost reference.
- * \param [in] ghostSize - the ghost size of zone for all axis.
- */
-void MEDCouplingCartesianAMRMeshGen::ApplyGhostOnCompactFrmt(std::vector< std::pair<int,int> >& partBeforeFact, int ghostSize)
-{
-  if(ghostSize<0)
-    throw INTERP_KERNEL::Exception("MEDCouplingCartesianAMRMeshGen::ApplyGhostOnCompactFrmt : ghost size must be >= 0 !");
-  std::size_t sz(partBeforeFact.size());
-  for(std::size_t i=0;i<sz;i++)
+  if(ghostLev<0)
+    throw INTERP_KERNEL::Exception("MEDCouplingCartesianAMRMesh::GetGhostLevelInFineRef : the ghost size must be >=0 !");
+  if(factors.empty())
+    throw INTERP_KERNEL::Exception("MEDCouplingCartesianAMRMesh::GetGhostLevelInFineRef : no factors defined !");
+  int ghostLevInPatchRef;
+  if(ghostLev==0)
+    ghostLevInPatchRef=0;
+  else
     {
-      partBeforeFact[i].first+=ghostSize;
-      partBeforeFact[i].second+=ghostSize;
+      ghostLevInPatchRef=(ghostLev-1)/factors[0]+1;
+      for(std::size_t i=0;i<factors.size();i++)
+        ghostLevInPatchRef=std::max(ghostLevInPatchRef,(ghostLev-1)/factors[i]+1);
     }
+  return ghostLevInPatchRef;
 }
 
 /*!
- * This method is different than ApplyGhostOnCompactFrmt
- *
- * \param [in,out] partBeforeFact - the part of a image mesh in compact format that will be put in ghost reference.
- * \param [in] ghostSize - the ghost size of zone for all axis.
+ * This method returns a sub set of \a all. The subset is defined by the \a head in the tree defined by \a this.
+ * Elements in \a all are expected to be sorted from god father to most refined structure.
  */
-void MEDCouplingCartesianAMRMeshGen::ApplyAllGhostOnCompactFrmt(std::vector< std::pair<int,int> >& partBeforeFact, int ghostSize)
+std::vector<const DataArrayDouble *> MEDCouplingCartesianAMRMeshGen::extractSubTreeFromGlobalFlatten(const MEDCouplingCartesianAMRMeshGen *head, const std::vector<const DataArrayDouble *>& all) const
 {
-  if(ghostSize<0)
-    throw INTERP_KERNEL::Exception("MEDCouplingCartesianAMRMeshGen::ApplyAllGhostOnCompactFrmt : ghost size must be >= 0 !");
-  std::size_t sz(partBeforeFact.size());
-  for(std::size_t i=0;i<sz;i++)
+  int maxLev(getMaxNumberOfLevelsRelativeToThis());
+  std::vector<const DataArrayDouble *> ret;
+  std::vector<const MEDCouplingCartesianAMRMeshGen *> meshes(1,this);
+  std::size_t kk(0);
+  for(int i=0;i<maxLev;i++)
     {
-      partBeforeFact[i].first-=ghostSize;
-      partBeforeFact[i].second+=ghostSize;
+      std::vector<const MEDCouplingCartesianAMRMeshGen *> meshesTmp;
+      for(std::vector<const MEDCouplingCartesianAMRMeshGen *>::const_iterator it=meshes.begin();it!=meshes.end();it++)
+        {
+          if((*it)==head || head->isObjectInTheProgeny(*it))
+            ret.push_back(all[kk]);
+          kk++;
+          std::vector< const MEDCouplingCartesianAMRPatch *> ps((*it)->getPatches());
+          for(std::vector< const MEDCouplingCartesianAMRPatch *>::const_iterator it0=ps.begin();it0!=ps.end();it0++)
+            {
+              const MEDCouplingCartesianAMRMeshGen *mesh((*it0)->getMesh());
+              meshesTmp.push_back(mesh);
+            }
+        }
+      meshes=meshesTmp;
     }
+  if(kk!=all.size())
+    throw INTERP_KERNEL::Exception("MEDCouplingCartesianAMRMeshGen::extractSubTreeFromGlobalFlatten : the size of input vector is not compatible with number of leaves in this !");
+  return ret;
 }
 
 std::size_t MEDCouplingCartesianAMRMeshGen::getHeapMemorySizeWithoutChildren() const
@@ -1039,7 +1444,54 @@ MEDCouplingCartesianAMRMesh *MEDCouplingCartesianAMRMesh::New(const std::string&
   return new MEDCouplingCartesianAMRMesh(meshName,spaceDim,nodeStrctStart,nodeStrctStop,originStart,originStop,dxyzStart,dxyzStop);
 }
 
+void MEDCouplingCartesianAMRMesh::setData(MEDCouplingDataForGodFather *data)
+{
+  MEDCouplingDataForGodFather *myData(_data);
+  if(myData==data)
+    return ;
+  if(myData)
+    myData->changeGodFather(0);
+  _data=data;
+  if(data)
+    data->incrRef();
+}
+
+void MEDCouplingCartesianAMRMesh::allocData() const
+{
+  checkData();
+  _data->alloc();
+}
+
+void MEDCouplingCartesianAMRMesh::deallocData() const
+{
+  checkData();
+  _data->dealloc();
+}
+
 MEDCouplingCartesianAMRMesh::MEDCouplingCartesianAMRMesh(const std::string& meshName, int spaceDim, const int *nodeStrctStart, const int *nodeStrctStop,
                                                          const double *originStart, const double *originStop, const double *dxyzStart, const double *dxyzStop):MEDCouplingCartesianAMRMeshGen(meshName,spaceDim,nodeStrctStart,nodeStrctStop,originStart,originStop,dxyzStart,dxyzStop)
 {
 }
+
+std::vector<const BigMemoryObject *> MEDCouplingCartesianAMRMesh::getDirectChildren() const
+{
+  std::vector<const BigMemoryObject *> ret(MEDCouplingCartesianAMRMeshGen::getDirectChildren());
+  const MEDCouplingDataForGodFather *pt(_data);
+  if(pt)
+    ret.push_back(pt);
+  return ret;
+}
+
+void MEDCouplingCartesianAMRMesh::checkData() const
+{
+  const MEDCouplingDataForGodFather *data(_data);
+  if(!data)
+    throw INTERP_KERNEL::Exception("MEDCouplingCartesianAMRMesh::checkData : no data set !");
+}
+
+MEDCouplingCartesianAMRMesh::~MEDCouplingCartesianAMRMesh()
+{
+  MEDCouplingDataForGodFather *data(_data);
+  if(data)
+    data->changeGodFather(0);
+}