Salome HOME
Ensure sequential run of MEDLoader 1,2,3 tests.
[tools/medcoupling.git] / src / MEDCoupling / MEDCouplingCartesianAMRMesh.cxx
index e5f3e1c718a6db801e541f9f327d016262636a7e..b8ee9e24ea5dc25d2f201e81541e83f167f01ca6 100644 (file)
@@ -1,4 +1,4 @@
-// Copyright (C) 2007-2014  CEA/DEN, EDF R&D
+// Copyright (C) 2007-2015  CEA/DEN, EDF R&D
 //
 // This library is free software; you can redistribute it and/or
 // modify it under the terms of the GNU Lesser General Public
@@ -19,6 +19,7 @@
 // Author : Anthony Geay
 
 #include "MEDCouplingCartesianAMRMesh.hxx"
+#include "MEDCouplingAMRAttribute.hxx"
 #include "MEDCouplingFieldDouble.hxx"
 #include "MEDCoupling1GTUMesh.hxx"
 #include "MEDCouplingIMesh.hxx"
@@ -28,7 +29,7 @@
 #include <sstream>
 #include <numeric>
 
-using namespace ParaMEDMEM;
+using namespace MEDCoupling;
 
 /// @cond INTERNAL
 
@@ -54,6 +55,13 @@ MEDCouplingCartesianAMRPatchGen::MEDCouplingCartesianAMRPatchGen(MEDCouplingCart
   _mesh=mesh; _mesh->incrRef();
 }
 
+MEDCouplingCartesianAMRPatchGen::MEDCouplingCartesianAMRPatchGen(const MEDCouplingCartesianAMRPatchGen& other, MEDCouplingCartesianAMRMeshGen *father):RefCountObject(other),_mesh(other._mesh)
+{
+  const MEDCouplingCartesianAMRMeshGen *mesh(other._mesh);
+  if(mesh)
+    _mesh=mesh->deepCopy(father);
+}
+
 const MEDCouplingCartesianAMRMeshGen *MEDCouplingCartesianAMRPatchGen::getMeshSafe() const
 {
   const MEDCouplingCartesianAMRMeshGen *mesh(_mesh);
@@ -70,11 +78,10 @@ MEDCouplingCartesianAMRMeshGen *MEDCouplingCartesianAMRPatchGen::getMeshSafe()
     return mesh;
 }
 
-std::vector<const BigMemoryObject *> MEDCouplingCartesianAMRPatchGen::getDirectChildren() const
+std::vector<const BigMemoryObject *> MEDCouplingCartesianAMRPatchGen::getDirectChildrenWithNull() const
 {
   std::vector<const BigMemoryObject *> ret;
-  if((const MEDCouplingCartesianAMRMeshGen *)_mesh)
-    ret.push_back((const MEDCouplingCartesianAMRMeshGen *)_mesh);
+  ret.push_back((const MEDCouplingCartesianAMRMeshGen *)_mesh);
   return ret;
 }
 
@@ -90,6 +97,11 @@ MEDCouplingCartesianAMRPatch::MEDCouplingCartesianAMRPatch(MEDCouplingCartesianA
     throw INTERP_KERNEL::Exception("MEDCouplingCartesianAMRPatch constructor : space dimension of father and input bottomLeft/topRight size mismatches !");
 }
 
+MEDCouplingCartesianAMRPatch *MEDCouplingCartesianAMRPatch::deepCopy(MEDCouplingCartesianAMRMeshGen *father) const
+{
+  return new MEDCouplingCartesianAMRPatch(*this,father);
+}
+
 void MEDCouplingCartesianAMRPatch::addPatch(const std::vector< std::pair<int,int> >& bottomLeftTopRight, const std::vector<int>& factors)
 {
   return getMeshSafe()->addPatch(bottomLeftTopRight,factors);
@@ -122,7 +134,7 @@ 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());
-  return IsInMyNeighborhood(ghostLev,thisp,otherp);
+  return IsInMyNeighborhood(ghostLev==0?0:1,thisp,otherp);//make hypothesis that nb this->_mesh->getFather->getFactors() is >= ghostLev
 }
 
 /*!
@@ -160,7 +172,7 @@ bool MEDCouplingCartesianAMRPatch::isInMyNeighborhoodExt(const MEDCouplingCartes
 /*!
  * 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.
- * This is expected to be more refined than \a other. That is to say lev of \a this is greater than level of \a other.
+ * \a this is expected to be more refined than \a other. That is to say lev of \a this is greater than level of \a other.
  *
  * \param [in] other - The other patch
  * \param [in] ghostLev - The size of the neighborhood zone.
@@ -177,7 +189,44 @@ bool MEDCouplingCartesianAMRPatch::isInMyNeighborhoodDiffLev(const MEDCouplingCa
   std::vector< std::pair<int,int> > thispp,otherpp;
   std::vector<int> factors;
   ComputeZonesOfTwoRelativeToOneDiffLev(ghostLev,this,other,thispp,otherpp,factors);
-  return IsInMyNeighborhood(ghostLev,thispp,otherpp);
+  return IsInMyNeighborhood(ghostLev>0?1:0,thispp,otherpp);//1 not ghostLev ! It is not a bug ( I hope :) ) ! Because as \a this is a refinement of \a other ghostLev is supposed to be <= factors
+}
+
+std::vector< std::pair<int,int> > MEDCouplingCartesianAMRPatch::getBLTRRangeRelativeToGF() const
+{
+  std::vector< std::pair<int,int> > ret(_bl_tr);
+  const MEDCouplingCartesianAMRMeshGen *mesh(getMesh());
+  if(!mesh)
+    throw INTERP_KERNEL::Exception("MEDCouplingCartesianAMRPatch::getBLTRRangeRelativeToGF : not valid !");
+  const MEDCouplingCartesianAMRMeshGen *fath(mesh->getFather());
+  if(!fath)
+    throw INTERP_KERNEL::Exception("MEDCouplingCartesianAMRPatch::getBLTRRangeRelativeToGF : not valid 2 !");
+  std::vector<int> factors(fath->getFactors());
+  std::size_t sz(ret.size());
+  for(std::size_t ii=0;ii<sz;ii++)
+    {
+      ret[ii].first*=factors[ii];
+      ret[ii].second*=factors[ii];
+    }
+  const MEDCouplingCartesianAMRMeshGen *oldFather(fath);
+  fath=oldFather->getFather();
+  while(fath)
+    {
+      int pos(fath->getPatchIdFromChildMesh(oldFather));
+      const MEDCouplingCartesianAMRPatch *p(fath->getPatch(pos));
+      const std::vector< std::pair<int,int> >& tmp(p->getBLTRRange());
+      const std::vector<int>& factors2(fath->getFactors());
+      std::transform(factors.begin(),factors.end(),factors2.begin(),factors.begin(),std::multiplies<int>());
+      for(std::size_t ii=0;ii<sz;ii++)
+        {
+          int delta(ret[ii].second-ret[ii].first);
+          ret[ii].first+=tmp[ii].first*factors[ii];
+          ret[ii].second=ret[ii].first+delta;
+        }
+      oldFather=fath;
+      fath=oldFather->getFather();
+    }
+  return ret;
 }
 
 std::vector<int> MEDCouplingCartesianAMRPatch::computeCellGridSt() const
@@ -236,7 +285,7 @@ std::vector< std::vector< std::pair<const MEDCouplingCartesianAMRPatch *,const M
         {
           for(std::vector<const MEDCouplingCartesianAMRPatch *>::const_iterator it2=p2Work.begin();it2!=p2Work.end();it2++)
             {
-              if((*it1)->isInMyNeighborhoodExt(*it2,ghostLev))
+              if((*it1)->isInMyNeighborhoodExt(*it2,ghostLev>0?1:0))//1 not ghostLev ! It is not a bug ( I hope :) ) ! Because as \a this is a refinement of \a other ghostLev is supposed to be <= factors
                 retTmp.push_back(std::pair<const MEDCouplingCartesianAMRPatch *,const MEDCouplingCartesianAMRPatch *>(*it1,*it2));
             }
           std::vector<const MEDCouplingCartesianAMRPatch *> tmp1((*it1)->getMesh()->getPatches());
@@ -311,7 +360,7 @@ void MEDCouplingCartesianAMRPatch::UpdateNeighborsOfOneWithTwoExt(int ghostLev,
 /*!
  * \a p1 is expected to be more refined than \a p2. \a p1 and \a p2 have to share a common ancestor. Compared to UpdateNeighborsOfOneWithTwoExt here \a p1 and \a p2 are \b not at the same level !
  */
-void MEDCouplingCartesianAMRPatch::UpdateNeighborsOfOneWithTwoMixedLev(int ghostLev, const MEDCouplingCartesianAMRPatch *p1, const MEDCouplingCartesianAMRPatch *p2, DataArrayDouble *dataOnP1, const DataArrayDouble *dataOnP2)
+void MEDCouplingCartesianAMRPatch::UpdateNeighborsOfOneWithTwoMixedLev(int ghostLev, const MEDCouplingCartesianAMRPatch *p1, const MEDCouplingCartesianAMRPatch *p2, DataArrayDouble *dataOnP1, const DataArrayDouble *dataOnP2, bool isConservative)
 {
   std::vector< std::pair<int,int> > p1pp,p2pp;
   std::vector<int> factors;
@@ -323,8 +372,13 @@ void MEDCouplingCartesianAMRPatch::UpdateNeighborsOfOneWithTwoMixedLev(int ghost
   std::vector< std::pair<int,int> > p2RefinedAbs(MEDCouplingStructuredMesh::GetCompactFrmtFromDimensions(dimsP2NotRefined));
   std::vector<int> dimsP2RefinedGhost(dimsP2Refined.size());
   std::transform(dimsP2Refined.begin(),dimsP2Refined.end(),dimsP2RefinedGhost.begin(),std::bind2nd(std::plus<int>(),2*ghostLev));
-  MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> fineP2(DataArrayDouble::New()); fineP2->alloc(MEDCouplingStructuredMesh::DeduceNumberOfGivenStructure(dimsP2RefinedGhost),dataOnP2->getNumberOfComponents());
+  MCAuto<DataArrayDouble> fineP2(DataArrayDouble::New()); fineP2->alloc(MEDCouplingStructuredMesh::DeduceNumberOfGivenStructure(dimsP2RefinedGhost),dataOnP2->getNumberOfComponents());
   MEDCouplingIMesh::SpreadCoarseToFineGhost(dataOnP2,dimsP2NotRefined,fineP2,p2RefinedAbs,factors,ghostLev);
+  if(isConservative)
+    {
+      int fact(MEDCouplingStructuredMesh::DeduceNumberOfGivenStructure(factors));
+      std::transform(fineP2->begin(),fineP2->end(),fineP2->getPointer(),std::bind2nd(std::multiplies<double>(),1./((double)fact)));
+    }
   //
   UpdateNeighborsOfOneWithTwoInternal(ghostLev,p1->getMesh()->getFather()->getFactors(),p1pp,p2pp,dataOnP1,fineP2);
 }
@@ -462,7 +516,7 @@ void MEDCouplingCartesianAMRPatch::UpdateNeighborsOfOneWithTwoInternal(int ghost
   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)]
+  MEDCouplingStructuredMesh::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)]
@@ -472,10 +526,14 @@ void MEDCouplingCartesianAMRPatch::UpdateNeighborsOfOneWithTwoInternal(int ghost
   ApplyFactorsOnCompactFrmt(dimsFine,factors);
   ApplyAllGhostOnCompactFrmt(dimsFine,ghostLev);
   //
-  MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> ghostVals(MEDCouplingStructuredMesh::ExtractFieldOfDoubleFrom(MEDCouplingStructuredMesh::GetDimensionsFromCompactFrmt(dimsFine),dataOnP2,tmp2));
+  MCAuto<DataArrayDouble> ghostVals(MEDCouplingStructuredMesh::ExtractFieldOfDoubleFrom(MEDCouplingStructuredMesh::GetDimensionsFromCompactFrmt(dimsFine),dataOnP2,tmp2));
   MEDCouplingIMesh::CondenseFineToCoarse(dimsCoarse,ghostVals,interstRange,fakeFactors,dataOnP1);
 }
 
+MEDCouplingCartesianAMRPatch::MEDCouplingCartesianAMRPatch(const MEDCouplingCartesianAMRPatch& other, MEDCouplingCartesianAMRMeshGen *father):MEDCouplingCartesianAMRPatchGen(other,father),_bl_tr(other._bl_tr)
+{
+}
+
 /*!
  * \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.
@@ -492,22 +550,6 @@ void MEDCouplingCartesianAMRPatch::ApplyFactorsOnCompactFrmt(std::vector< std::p
     }
 }
 
-/*!
- * \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.
  *
@@ -530,31 +572,18 @@ MEDCouplingCartesianAMRPatchGF::MEDCouplingCartesianAMRPatchGF(MEDCouplingCartes
 {
 }
 
-std::size_t MEDCouplingCartesianAMRPatchGF::getHeapMemorySizeWithoutChildren() const
+MEDCouplingCartesianAMRPatchGF *MEDCouplingCartesianAMRPatchGF::deepCopy(MEDCouplingCartesianAMRMeshGen *father) const
 {
-  return sizeof(MEDCouplingCartesianAMRPatchGF);
+  return new MEDCouplingCartesianAMRPatchGF(*this,father);
 }
 
-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
+std::size_t MEDCouplingCartesianAMRPatchGF::getHeapMemorySizeWithoutChildren() const
 {
-  _tlc.checkConst();
+  return sizeof(MEDCouplingCartesianAMRPatchGF);
 }
 
-bool MEDCouplingDataForGodFather::changeGodFather(MEDCouplingCartesianAMRMesh *gf)
+MEDCouplingCartesianAMRPatchGF::MEDCouplingCartesianAMRPatchGF(const MEDCouplingCartesianAMRPatchGF& other, MEDCouplingCartesianAMRMeshGen *father):MEDCouplingCartesianAMRPatchGen(other,father)
 {
-  bool ret(_tlc.keepTrackOfNewTL(gf));
-  if(ret)
-    {
-      _gf=gf;
-    }
-  return ret;
 }
 
 /// @endcond
@@ -584,7 +613,7 @@ void MEDCouplingCartesianAMRMeshGen::setFactors(const std::vector<int>& newFacto
 int MEDCouplingCartesianAMRMeshGen::getMaxNumberOfLevelsRelativeToThis() const
 {
   int ret(1);
-  for(std::vector< MEDCouplingAutoRefCountObjectPtr<MEDCouplingCartesianAMRPatch> >::const_iterator it=_patches.begin();it!=_patches.end();it++)
+  for(std::vector< MCAuto<MEDCouplingCartesianAMRPatch> >::const_iterator it=_patches.begin();it!=_patches.end();it++)
     ret=std::max(ret,(*it)->getMaxNumberOfLevelsRelativeToThis()+1);
   return ret;
 }
@@ -608,7 +637,7 @@ int MEDCouplingCartesianAMRMeshGen::getNumberOfCellsAtCurrentLevel() const
  */
 int MEDCouplingCartesianAMRMeshGen::getNumberOfCellsAtCurrentLevelGhost(int ghostLev) const
 {
-  MEDCouplingAutoRefCountObjectPtr<MEDCouplingIMesh> tmp(_mesh->buildWithGhost(ghostLev));
+  MCAuto<MEDCouplingIMesh> tmp(_mesh->buildWithGhost(ghostLev));
   return tmp->getNumberOfCells();
 }
 
@@ -619,7 +648,7 @@ int MEDCouplingCartesianAMRMeshGen::getNumberOfCellsAtCurrentLevelGhost(int ghos
 int MEDCouplingCartesianAMRMeshGen::getNumberOfCellsRecursiveWithOverlap() const
 {
   int ret(_mesh->getNumberOfCells());
-  for(std::vector< MEDCouplingAutoRefCountObjectPtr<MEDCouplingCartesianAMRPatch> >::const_iterator it=_patches.begin();it!=_patches.end();it++)
+  for(std::vector< MCAuto<MEDCouplingCartesianAMRPatch> >::const_iterator it=_patches.begin();it!=_patches.end();it++)
     {
       ret+=(*it)->getNumberOfCellsRecursiveWithOverlap();
     }
@@ -636,7 +665,7 @@ int MEDCouplingCartesianAMRMeshGen::getNumberOfCellsRecursiveWithOverlap() const
 int MEDCouplingCartesianAMRMeshGen::getNumberOfCellsRecursiveWithoutOverlap() const
 {
   int ret(_mesh->getNumberOfCells());
-  for(std::vector< MEDCouplingAutoRefCountObjectPtr<MEDCouplingCartesianAMRPatch> >::const_iterator it=_patches.begin();it!=_patches.end();it++)
+  for(std::vector< MCAuto<MEDCouplingCartesianAMRPatch> >::const_iterator it=_patches.begin();it!=_patches.end();it++)
     {
       ret-=(*it)->getNumberOfOverlapedCellsForFather();
       ret+=(*it)->getNumberOfCellsRecursiveWithoutOverlap();
@@ -644,28 +673,57 @@ int MEDCouplingCartesianAMRMeshGen::getNumberOfCellsRecursiveWithoutOverlap() co
   return ret;
 }
 
-const MEDCouplingCartesianAMRMeshGen *MEDCouplingCartesianAMRMeshGen::getFather() const
+/*!
+ * This method returns a vector of size equal to getAbsoluteLevelRelativeTo. It allows to find position an absolute position of \a this
+ * relative to \a ref (that is typically the god father).
+ *
+ * \sa getPatchAtPosition
+ */
+std::vector<int> MEDCouplingCartesianAMRMeshGen::getPositionRelativeTo(const MEDCouplingCartesianAMRMeshGen *ref) const
 {
-  return _father;
+  if(!ref)
+    throw INTERP_KERNEL::Exception("MEDCouplingCartesianAMRMeshGen::getPositionRelativeTo : input pointer is NULL !");
+  std::vector<int> ret;
+  getPositionRelativeToInternal(ref,ret);
+  std::reverse(ret.begin(),ret.end());
+  return ret;
 }
 
-const MEDCouplingCartesianAMRMeshGen *MEDCouplingCartesianAMRMeshGen::getGodFather() const
+/*!
+ * \sa getPositionRelativeTo, getMeshAtPosition
+ */
+const MEDCouplingCartesianAMRPatch *MEDCouplingCartesianAMRMeshGen::getPatchAtPosition(const std::vector<int>& pos) const
 {
-  if(_father==0)
-    return this;
-  else
-    return _father->getGodFather();
+  std::size_t sz(pos.size());
+  if(sz==0)
+    throw INTERP_KERNEL::Exception("MEDCouplingCartesianAMRMeshGen::getPatchAtPosition : empty input -> no patch by definition !");
+  int patchId(pos[0]);
+  const MEDCouplingCartesianAMRPatch *elt(getPatch(patchId));
+  if(sz==1)
+    return elt;
+  if(!elt || !elt->getMesh())
+    throw INTERP_KERNEL::Exception("MEDCouplingCartesianAMRMeshGen::getPatchAtPosition : NULL element found during walk !");
+  std::vector<int> pos2(pos.begin()+1,pos.end());
+  return elt->getMesh()->getPatchAtPosition(pos2);
 }
 
-/*!
- * This method returns the level of \a this. 0 for god father. -1 for children of god father ...
- */
-int MEDCouplingCartesianAMRMeshGen::getAbsoluteLevel() const
+const MEDCouplingCartesianAMRMeshGen *MEDCouplingCartesianAMRMeshGen::getMeshAtPosition(const std::vector<int>& pos) const
 {
-  if(_father==0)
-    return 0;
-  else
-    return _father->getAbsoluteLevel()-1;
+  std::size_t sz(pos.size());
+  if(sz==0)
+    return this;
+  int patchId(pos[0]);
+  const MEDCouplingCartesianAMRPatch *elt(getPatch(patchId));
+  if(sz==1)
+    {
+      if(!elt)
+        throw INTERP_KERNEL::Exception("MEDCouplingCartesianAMRMeshGen::getMeshAtPosition : NULL patch !");
+      return elt->getMesh();
+    }
+  if(!elt || !elt->getMesh())
+    throw INTERP_KERNEL::Exception("MEDCouplingCartesianAMRMeshGen::getPatchAtPosition : NULL element found during walk !");
+  std::vector<int> pos2(pos.begin()+1,pos.end());
+  return elt->getMesh()->getMeshAtPosition(pos2);
 }
 
 /*!
@@ -677,23 +735,7 @@ std::vector<MEDCouplingCartesianAMRPatchGen *> MEDCouplingCartesianAMRMeshGen::r
 {
   if(absoluteLev<0)
     throw INTERP_KERNEL::Exception("MEDCouplingCartesianAMRMesh::retrieveGridsAt : absolute level must be >=0 !");
-  if(_father)
-    return getGodFather()->retrieveGridsAt(absoluteLev);
-  //
-  std::vector< MEDCouplingAutoRefCountObjectPtr<MEDCouplingCartesianAMRPatchGen> > rets;
-  retrieveGridsAtInternal(absoluteLev,rets);
-  std::vector< MEDCouplingCartesianAMRPatchGen * > ret(rets.size());
-  for(std::size_t i=0;i<rets.size();i++)
-    {
-      ret[i]=rets[i].retn();
-    }
-  return ret;
-}
-
-void MEDCouplingCartesianAMRMeshGen::detachFromFather()
-{
-  _father=0;
-  declareAsNew();
+  return getGodFather()->retrieveGridsAt(absoluteLev);
 }
 
 /*!
@@ -704,10 +746,10 @@ void MEDCouplingCartesianAMRMeshGen::detachFromFather()
 void MEDCouplingCartesianAMRMeshGen::addPatch(const std::vector< std::pair<int,int> >& bottomLeftTopRight, const std::vector<int>& factors)
 {
   checkFactorsAndIfNotSetAssign(factors);
-  MEDCouplingAutoRefCountObjectPtr<MEDCouplingIMesh> mesh(static_cast<MEDCouplingIMesh *>(_mesh->buildStructuredSubPart(bottomLeftTopRight)));
+  MCAuto<MEDCouplingIMesh> mesh(static_cast<MEDCouplingIMesh *>(_mesh->buildStructuredSubPart(bottomLeftTopRight)));
   mesh->refineWithFactor(factors);
-  MEDCouplingAutoRefCountObjectPtr<MEDCouplingCartesianAMRMeshSub> zeMesh(new MEDCouplingCartesianAMRMeshSub(this,mesh));
-  MEDCouplingAutoRefCountObjectPtr<MEDCouplingCartesianAMRPatch> elt(new MEDCouplingCartesianAMRPatch(zeMesh,bottomLeftTopRight));
+  MCAuto<MEDCouplingCartesianAMRMeshSub> zeMesh(new MEDCouplingCartesianAMRMeshSub(this,mesh));
+  MCAuto<MEDCouplingCartesianAMRPatch> elt(new MEDCouplingCartesianAMRPatch(zeMesh,bottomLeftTopRight));
   _patches.push_back(elt);
   declareAsNew();
 }
@@ -731,10 +773,10 @@ public:
   std::vector<int> computeCGS() const { return MEDCouplingStructuredMesh::GetDimensionsFromCompactFrmt(_part); }
   std::vector< std::vector<int> > computeSignature() const { return MEDCouplingStructuredMesh::ComputeSignaturePerAxisOf(computeCGS(),getConstCriterion()); }
   double getEfficiencyPerAxis(int axisId) const { return (double)_nb_of_true/((double)(_part[axisId].second-_part[axisId].first)); }
-  void zipToFitOnCriterion();
+  void zipToFitOnCriterion(int minPatchLgth);
   void updateNumberOfTrue() const;
-  MEDCouplingAutoRefCountObjectPtr<InternalPatch> extractPart(const std::vector< std::pair<int,int> >&partInGlobal) const;
-  MEDCouplingAutoRefCountObjectPtr<InternalPatch> deepCpy() const;
+  MCAuto<InternalPatch> extractPart(const std::vector< std::pair<int,int> >&partInGlobal) const;
+  MCAuto<InternalPatch> deepCopy() const;
 protected:
   ~InternalPatch() { }
 private:
@@ -744,12 +786,12 @@ private:
   std::vector< std::pair<int,int> > _part;
 };
 
-void InternalPatch::zipToFitOnCriterion()
+void InternalPatch::zipToFitOnCriterion(int minPatchLgth)
 {
   std::vector<int> cgs(computeCGS());
   std::vector<bool> newCrit;
   std::vector< std::pair<int,int> > newPart,newPart2;
-  int newNbOfTrue(MEDCouplingStructuredMesh::FindMinimalPartOf(cgs,_crit,newCrit,newPart));
+  int newNbOfTrue(MEDCouplingStructuredMesh::FindMinimalPartOf(minPatchLgth,cgs,_crit,newCrit,newPart));
   MEDCouplingStructuredMesh::ChangeReferenceToGlobalOfCompactFrmt(_part,newPart,newPart2);
   if(newNbOfTrue!=_nb_of_true)
     throw INTERP_KERNEL::Exception("InternalPatch::zipToFitOnCrit : internal error !");
@@ -761,9 +803,9 @@ void InternalPatch::updateNumberOfTrue() const
   _nb_of_true=(int)std::count(_crit.begin(),_crit.end(),true);
 }
 
-MEDCouplingAutoRefCountObjectPtr<InternalPatch> InternalPatch::extractPart(const std::vector< std::pair<int,int> >&partInGlobal) const
+MCAuto<InternalPatch> InternalPatch::extractPart(const std::vector< std::pair<int,int> >&partInGlobal) const
 {
-  MEDCouplingAutoRefCountObjectPtr<InternalPatch> ret(new InternalPatch);
+  MCAuto<InternalPatch> ret(new InternalPatch);
   std::vector<int> cgs(computeCGS());
   std::vector< std::pair<int,int> > newPart;
   MEDCouplingStructuredMesh::ChangeReferenceFromGlobalOfCompactFrmt(_part,partInGlobal,newPart);
@@ -773,53 +815,52 @@ MEDCouplingAutoRefCountObjectPtr<InternalPatch> InternalPatch::extractPart(const
   return ret;
 }
 
-MEDCouplingAutoRefCountObjectPtr<InternalPatch> InternalPatch::deepCpy() const
+MCAuto<InternalPatch> InternalPatch::deepCopy() const
 {
-  MEDCouplingAutoRefCountObjectPtr<InternalPatch> ret(new InternalPatch);
+  MCAuto<InternalPatch> ret(new InternalPatch);
   (*ret)=*this;
   return ret;
 }
 
-void DissectBigPatch(const INTERP_KERNEL::BoxSplittingOptions& bso, const InternalPatch *patchToBeSplit, int axisId, int rangeOfAxisId, bool& cutFound, int& cutPlace)
+void DissectBigPatch(const INTERP_KERNEL::BoxSplittingOptions& bso, const InternalPatch *patchToBeSplit, int axisId, int largestLength, int& cutPlace)
 {
-  cutFound=false; cutPlace=-1;
-  std::vector<double> ratio(rangeOfAxisId-1);
-  for(int id=0;id<rangeOfAxisId-1;id++)
+  int minimumPatchLength(bso.getMinimumPatchLength());
+  std::vector<double> ratio(largestLength-minimumPatchLength,std::numeric_limits<double>::max());
+  int index_min = -1;
+  double minSemiEfficiencyRatio(std::numeric_limits<double>::max());
+  double efficiencyPerAxis[2];
+
+  for(int i=minimumPatchLength-1;i<largestLength-minimumPatchLength;i++)
     {
-      double efficiency[2];
       for(int h=0;h<2;h++)
         {
           std::vector< std::pair<int,int> > rectH(patchToBeSplit->getConstPart());
           if(h==0)
-            rectH[axisId].second=patchToBeSplit->getConstPart()[axisId].first+id;
+            rectH[axisId].second=patchToBeSplit->getConstPart()[axisId].first+i;
           else
-            rectH[axisId].first=patchToBeSplit->getConstPart()[axisId].first+id;
-          MEDCouplingAutoRefCountObjectPtr<InternalPatch> p(patchToBeSplit->deepCpy());
-          p->zipToFitOnCriterion();
-          //anouar rectH ?
-          efficiency[h]=p->getEfficiencyPerAxis(axisId);
+            rectH[axisId].first=patchToBeSplit->getConstPart()[axisId].first+i;
+          MCAuto<InternalPatch> p(patchToBeSplit->deepCopy());
+          p->zipToFitOnCriterion(bso.getMinimumPatchLength());
+          efficiencyPerAxis[h]=p->getEfficiencyPerAxis(axisId);
         }
-      ratio[id]=std::max(efficiency[0],efficiency[1])/std::min(efficiency[0],efficiency[1]);
-    }
-  int minCellDirection(bso.getMinCellDirection()),indexMin(-1);
-  int dimRatioInner(rangeOfAxisId-1-2*(minCellDirection-1));
-  std::vector<double> ratio_inner(dimRatioInner);
-  double minRatio(1.e10);
-  for(int i=0; i<dimRatioInner; i++)
-    {
-      if(ratio[minCellDirection-1+i]<minRatio)
+      ratio[i]=std::max(efficiencyPerAxis[0], efficiencyPerAxis[1]) / std::min(efficiencyPerAxis[0], efficiencyPerAxis[1]);
+      if(ratio[i]<minSemiEfficiencyRatio)
         {
-          minRatio=ratio[minCellDirection-1+i];
-          indexMin=i+minCellDirection;
+          minSemiEfficiencyRatio = ratio[i];
+          index_min = i;
         }
     }
-  cutFound=true; cutPlace=indexMin+patchToBeSplit->getConstPart()[axisId].first-1;
+
+  if(index_min==-1)
+    throw INTERP_KERNEL::Exception("DissectBigPatch : just call to Arthur !");
+
+  cutPlace=index_min+patchToBeSplit->getConstPart()[axisId].first;
 }
 
-void FindHole(const INTERP_KERNEL::BoxSplittingOptions& bso, const InternalPatch *patchToBeSplit, int& axisId, bool& cutFound, int& cutPlace)
+bool FindHole(const INTERP_KERNEL::BoxSplittingOptions& bso, const InternalPatch *patchToBeSplit, int axisId, int& cutPlace)
 {
-  cutPlace=-1; cutFound=false;
-  int minCellDirection(bso.getMinCellDirection());
+  cutPlace=-1;
+  int minimumPatchLength(bso.getMinimumPatchLength());
   const int dim(patchToBeSplit->getDimension());
   std::vector< std::vector<int> > signatures(patchToBeSplit->computeSignature());
   for(int id=0;id<dim;id++)
@@ -828,31 +869,35 @@ void FindHole(const INTERP_KERNEL::BoxSplittingOptions& bso, const InternalPatch
       std::vector<int> hole;
       std::vector<double> distance;
       int len((int)signature.size());
-      for(int i=0;i<len;i++)
+      for(int i=minimumPatchLength-1;i<len-minimumPatchLength;i++)
         if(signature[i]==0)
-          if(len>= 2*minCellDirection && i >= minCellDirection-1 && i <= len-minCellDirection-1)
-            hole.push_back(i);
+          hole.push_back(i);
       if(!hole.empty())
         {
-          double center(((double)len/2.));
+          int closestHoleToMiddle(hole[0]);
+          int oldDistanceToMiddle(std::abs(hole[0]-len/2));
+          int newDistanceToMiddle(oldDistanceToMiddle);
           for(std::size_t i=0;i<hole.size();i++)
-            distance.push_back(fabs(hole[i]+1.-center));
-
-          std::size_t posDistanceMin(std::distance(distance.begin(),std::min_element(distance.begin(),distance.end())));
-          cutFound=true;
-          axisId=id;
-          cutPlace=hole[posDistanceMin]+patchToBeSplit->getConstPart()[axisId].first+1;
-          return ;
+            {
+              newDistanceToMiddle=std::abs(hole[i]-len/2);
+              if(newDistanceToMiddle < oldDistanceToMiddle)
+                {
+                  oldDistanceToMiddle = newDistanceToMiddle;
+                  closestHoleToMiddle = hole[i];
+                }
+            }
+          cutPlace=closestHoleToMiddle+patchToBeSplit->getConstPart()[axisId].first;
+          return true;
         }
     }
+  return false;
 }
 
-void FindInflection(const INTERP_KERNEL::BoxSplittingOptions& bso, const InternalPatch *patchToBeSplit, bool& cutFound, int& cutPlace, int& axisId)
+bool FindInflection(const INTERP_KERNEL::BoxSplittingOptions& bso, const InternalPatch *patchToBeSplit, int& cutPlace, int& axisId)
 {
-  cutFound=false; cutPlace=-1;// do not set axisId before to be sure that cutFound was set to true
-
+  bool cutFound(false); cutPlace=-1;// do not set axisId before to be sure that cutFound was set to true
   const std::vector< std::pair<int,int> >& part(patchToBeSplit->getConstPart());
-  int sign,minCellDirection(bso.getMinCellDirection());
+  int sign,minimumPatchLength(bso.getMinimumPatchLength());
   const int dim(patchToBeSplit->getDimension());
 
   std::vector<int> zeroCrossDims(dim,-1);
@@ -862,18 +907,18 @@ void FindInflection(const INTERP_KERNEL::BoxSplittingOptions& bso, const Interna
     {
       const std::vector<int>& signature(signatures[id]);
 
-      std::vector<int> derivate_second_order,gradient_absolute,signe_change,zero_cross,edge,max_cross_list ;
+      std::vector<int> derivate_second_order,gradient_absolute,zero_cross,edge,max_cross_list ;
       std::vector<double> distance ;
 
-      for (unsigned int i=1;i<signature.size()-1;i++)
+      for(std::size_t i=1;i<signature.size()-1;i++)
         derivate_second_order.push_back(signature[i-1]-2*signature[i]+signature[i+1]) ;
 
       // Gradient absolute value
-      for ( unsigned int i=1;i<derivate_second_order.size();i++)
-        gradient_absolute.push_back(fabs(derivate_second_order[i]-derivate_second_order[i-1])) ;
+      for(std::size_t i=1;i<derivate_second_order.size();i++)
+        gradient_absolute.push_back(abs(derivate_second_order[i]-derivate_second_order[i-1])) ;
       if(derivate_second_order.empty())
         continue;
-      for (unsigned int i=0;i<derivate_second_order.size()-1;i++)
+      for(std::size_t i=1;i<derivate_second_order.size()-1;i++)
         {
           if (derivate_second_order[i]*derivate_second_order[i+1] < 0 )
             sign = -1 ;
@@ -882,12 +927,11 @@ void FindInflection(const INTERP_KERNEL::BoxSplittingOptions& bso, const Interna
           if (derivate_second_order[i]*derivate_second_order[i+1] == 0 )
             sign = 0 ;
           if ( sign==0 || sign==-1 )
-            if ( i >= (unsigned int)minCellDirection-2 && i <= signature.size()-minCellDirection-2 )
+            if ( i >= (std::size_t)minimumPatchLength-2 && i <= signature.size()-minimumPatchLength-2 )
               {
                 zero_cross.push_back(i) ;
                 edge.push_back(gradient_absolute[i]) ;
               }
-          signe_change.push_back(sign) ;
         }
       if ( zero_cross.size() > 0 )
         {
@@ -900,7 +944,7 @@ void FindInflection(const INTERP_KERNEL::BoxSplittingOptions& bso, const Interna
           for (unsigned int i=0;i<max_cross_list.size();i++)
             distance.push_back(fabs(max_cross_list[i]+1-center));
 
-          float distance_min=*min_element(distance.begin(),distance.end()) ;
+          double distance_min=*min_element(distance.begin(),distance.end()) ;
           int pos_distance_min=find(distance.begin(),distance.end(),distance_min)-distance.begin();
           int best_place = max_cross_list[pos_distance_min] + part[id].first ;
           if ( max_cross >=0 )
@@ -911,7 +955,6 @@ void FindInflection(const INTERP_KERNEL::BoxSplittingOptions& bso, const Interna
         }
       derivate_second_order.clear() ;
       gradient_absolute.clear() ;
-      signe_change.clear() ;
       zero_cross.clear() ;
       edge.clear() ;
       max_cross_list.clear() ;
@@ -937,136 +980,164 @@ void FindInflection(const INTERP_KERNEL::BoxSplittingOptions& bso, const Interna
       cutPlace=zeroCrossDims[max_cross_dims];
       axisId=max_cross_dims ;
     }
+  return cutFound;
 }
 
-void TryAction4(const INTERP_KERNEL::BoxSplittingOptions& bso, const InternalPatch *patchToBeSplit, int axisId, int rangeOfAxisId, bool& cutFound, int& cutPlace)
+bool TryAction4(const INTERP_KERNEL::BoxSplittingOptions& bso, const InternalPatch *patchToBeSplit, int axisId, int rangeOfAxisId, int& cutPlace)
 {
-  cutFound=false;
-  if(patchToBeSplit->getEfficiency()<=bso.getEffeciencySnd())
+  if(patchToBeSplit->getEfficiency()<=bso.getEfficiencyGoal())
     {
-      if(rangeOfAxisId>=2*bso.getMinCellDirection())
+      if(rangeOfAxisId>=2*bso.getMinimumPatchLength())
         {
-          cutFound=true;
           cutPlace=rangeOfAxisId/2+patchToBeSplit->getConstPart()[axisId].first-1;
         }
+      else
+        return false;
     }
   else
     {
-      if(patchToBeSplit->getNumberOfCells()>bso.getMaxCells())
+      if(patchToBeSplit->getNumberOfCells()>bso.getMaximumNbOfCellsInPatch() || rangeOfAxisId>bso.getMaximumPatchLength())
         {
-          DissectBigPatch(bso,patchToBeSplit,axisId,rangeOfAxisId,cutFound,cutPlace);
+          DissectBigPatch(bso,patchToBeSplit,axisId,rangeOfAxisId,cutPlace);
         }
+      else
+        return false;
     }
+  return true;
 }
 
-MEDCouplingAutoRefCountObjectPtr<InternalPatch> DealWithNoCut(const InternalPatch *patch)
+MCAuto<InternalPatch> DealWithNoCut(const InternalPatch *patch)
 {
-  MEDCouplingAutoRefCountObjectPtr<InternalPatch> ret(const_cast<InternalPatch *>(patch));
+  MCAuto<InternalPatch> ret(const_cast<InternalPatch *>(patch));
   ret->incrRef();
   return ret;
 }
 
-void DealWithCut(const InternalPatch *patchToBeSplit, int axisId, int cutPlace, std::vector<MEDCouplingAutoRefCountObjectPtr<InternalPatch> >& listOfPatches)
+void DealWithCut(double minPatchLgth, const InternalPatch *patchToBeSplit, int axisId, int cutPlace, std::vector<MCAuto<InternalPatch> >& listOfPatches)
 {
-  MEDCouplingAutoRefCountObjectPtr<InternalPatch> leftPart,rightPart;
+  MCAuto<InternalPatch> leftPart,rightPart;
   std::vector< std::pair<int,int> > rect(patchToBeSplit->getConstPart());
   std::vector< std::pair<int,int> > leftRect(rect),rightRect(rect);
   leftRect[axisId].second=cutPlace+1;
   rightRect[axisId].first=cutPlace+1;
   leftPart=patchToBeSplit->extractPart(leftRect);
   rightPart=patchToBeSplit->extractPart(rightRect);
-  leftPart->zipToFitOnCriterion(); rightPart->zipToFitOnCriterion();
+  leftPart->zipToFitOnCriterion(minPatchLgth); rightPart->zipToFitOnCriterion(minPatchLgth);
   listOfPatches.push_back(leftPart);
   listOfPatches.push_back(rightPart);
 }
 
 /// @endcond
 
+void MEDCouplingCartesianAMRMeshGen::removeAllPatches()
+{
+  _patches.clear();
+  declareAsNew();
+}
+
+void MEDCouplingCartesianAMRMeshGen::removePatch(int patchId)
+{
+  checkPatchId(patchId);
+  int sz((int)_patches.size()),j(0);
+  std::vector< MCAuto<MEDCouplingCartesianAMRPatch> > patches(sz-1);
+  for(int i=0;i<sz;i++)
+    if(i!=patchId)
+      patches[j++]=_patches[i];
+  (const_cast<MEDCouplingCartesianAMRMeshGen *>(_patches[patchId]->getMesh()))->detachFromFather();
+  _patches=patches;
+  declareAsNew();
+}
+
+int MEDCouplingCartesianAMRMeshGen::getNumberOfPatches() const
+{
+  return (int)_patches.size();
+}
+
 /*!
- * This method creates patches in \a this (by destroying the patches if any). This method uses \a criterion array as a field on cells on this level.
+ * This method is a generic algorithm to create patches in \a this (by destroying the patches if any).
+ * This method uses \a criterion array as a field on cells on this level.
+ * This method only create patches at level 0 relative to \a this.
+ *
+ * This generic algorithm can be degenerated into three child ones, depending on the arguments given; in particular depending
+ * on whether they are equal to 0 or not.
+ * 1/ If  minimumPatchLength = maximumPatchLength = maximumPatchVolume = 0, then we have the Berger-Rigoutsos algorithm.
+ * This algorithm was developed in 1991 and seems appropriate for sequential programming.
+ * 2/ If maximumPatchLength = 0, then we have the Livne algorithm.
+ * This algorithm was developed in 2004 and is an improvement of the Berger-Rigoutsos algorithm.
+ * 3/ If maximumPatchVolume = 0, the we have the lmin-lmax algorithm.
+ * This algorithm was developed by Arthur TALPAERT in 2014 and is an improvement of the Livne algorithm. It is especially
+ * appropriate for parallel computing, where one patch would be given to one CPU. See Arthur TALPAERT's 2014 CANUM poster
+ * for more information.
+ *
  */
 void MEDCouplingCartesianAMRMeshGen::createPatchesFromCriterion(const INTERP_KERNEL::BoxSplittingOptions& bso, const std::vector<bool>& criterion, const std::vector<int>& factors)
 {
   int nbCells(getNumberOfCellsAtCurrentLevel());
   if(nbCells!=(int)criterion.size())
-    throw INTERP_KERNEL::Exception("MEDCouplingCartesianAMRMesh::createPatchesFromCriterion : the number of tuples of criterion array must be equal to the number of cells at the current level !");
+    throw INTERP_KERNEL::Exception("MEDCouplingCartesianAMRMeshGen::createPatchesFromCriterion : the number of tuples of criterion array must be equal to the number of cells at the current level !");
   _patches.clear();
   std::vector<int> cgs(_mesh->getCellGridStructure());
-  std::vector< MEDCouplingAutoRefCountObjectPtr<InternalPatch> > listOfPatches,listOfPatchesOK;
+  std::vector< MCAuto<InternalPatch> > listOfPatches,listOfPatchesOK;
   //
-  MEDCouplingAutoRefCountObjectPtr<InternalPatch> p(new InternalPatch);
-  p->setNumberOfTrue(MEDCouplingStructuredMesh::FindMinimalPartOf(cgs,criterion,p->getCriterion(),p->getPart()));
+  MCAuto<InternalPatch> p(new InternalPatch);
+  p->setNumberOfTrue(MEDCouplingStructuredMesh::FindMinimalPartOf(bso.getMinimumPatchLength(),cgs,criterion,p->getCriterion(),p->getPart()));
   if(p->presenceOfTrue())
     listOfPatches.push_back(p);
   while(!listOfPatches.empty())
     {
-      std::vector< MEDCouplingAutoRefCountObjectPtr<InternalPatch> > listOfPatchesTmp;
-      for(std::vector< MEDCouplingAutoRefCountObjectPtr<InternalPatch> >::iterator it=listOfPatches.begin();it!=listOfPatches.end();it++)
+      std::vector< MCAuto<InternalPatch> > listOfPatchesTmp;
+      for(std::vector< MCAuto<InternalPatch> >::iterator it=listOfPatches.begin();it!=listOfPatches.end();it++)
         {
           //
-          int axisId,rangeOfAxisId,cutPlace;
-          bool cutFound;
-          MEDCouplingStructuredMesh::FindTheWidestAxisOfGivenRangeInCompactFrmt((*it)->getConstPart(),axisId,rangeOfAxisId);
-          if((*it)->getEfficiency()>=bso.getEffeciency() && (*it)->getNumberOfCells()<bso.getMaxCells())
-            { listOfPatchesOK.push_back(DealWithNoCut(*it)); continue; }//action 1
-          FindHole(bso,*it,axisId,cutFound,cutPlace);//axisId overwritten here if FindHole equal to true !
-          if(cutFound)
-            { DealWithCut(*it,axisId,cutPlace,listOfPatchesTmp); continue; }//action 2
-          FindInflection(bso,*it,cutFound,cutPlace,axisId);//axisId overwritten here if cutFound equal to true !
-          if(cutFound)
-            { DealWithCut(*it,axisId,cutPlace,listOfPatchesTmp); continue; }//action 3
-          TryAction4(bso,*it,axisId,rangeOfAxisId,cutFound,cutPlace);
-          if(cutFound)
-            { DealWithCut(*it,axisId,cutPlace,listOfPatchesTmp); continue; }//action 4
-          listOfPatchesOK.push_back(DealWithNoCut(*it));
+          int axisId,largestLength,cutPlace;
+          MEDCouplingStructuredMesh::FindTheWidestAxisOfGivenRangeInCompactFrmt((*it)->getConstPart(),axisId,largestLength);
+          if((*it)->getEfficiency()>=bso.getEfficiencyThreshold() && ((*it)->getNumberOfCells()>bso.getMaximumNbOfCellsInPatch() || largestLength>bso.getMaximumPatchLength()))
+            {
+              DissectBigPatch(bso,*it,axisId,largestLength,cutPlace);
+              DealWithCut(bso.getMinimumPatchLength(),*it,axisId,cutPlace,listOfPatchesTmp);
+              continue;
+            }//action 1
+          if(FindHole(bso,*it,axisId,cutPlace))//axisId overwritten here if FindHole equal to true !
+            { DealWithCut(bso.getMinimumPatchLength(),*it,axisId,cutPlace,listOfPatchesTmp); continue; }//action 2
+          if(FindInflection(bso,*it,cutPlace,axisId))//axisId overwritten here if cutFound equal to true !
+            { DealWithCut(bso.getMinimumPatchLength(),*it,axisId,cutPlace,listOfPatchesTmp); continue; }//action 3
+          if(TryAction4(bso,*it,axisId,largestLength,cutPlace))
+            { DealWithCut(bso.getMinimumPatchLength(),*it,axisId,cutPlace,listOfPatchesTmp); continue; }//action 4
+          else
+            listOfPatchesOK.push_back(DealWithNoCut(*it));
         }
       listOfPatches=listOfPatchesTmp;
     }
-  for(std::vector< MEDCouplingAutoRefCountObjectPtr<InternalPatch> >::const_iterator it=listOfPatchesOK.begin();it!=listOfPatchesOK.end();it++)
+  for(std::vector< MCAuto<InternalPatch> >::const_iterator it=listOfPatchesOK.begin();it!=listOfPatchesOK.end();it++)
     addPatch((*it)->getConstPart(),factors);
   declareAsNew();
 }
 
 /*!
  * This method creates patches in \a this (by destroying the patches if any). This method uses \a criterion array as a field on cells on this level.
+ * This method only create patches at level 0 relative to \a this.
  */
 void MEDCouplingCartesianAMRMeshGen::createPatchesFromCriterion(const INTERP_KERNEL::BoxSplittingOptions& bso, const DataArrayByte *criterion, const std::vector<int>& factors)
 {
   if(!criterion || !criterion->isAllocated())
-    throw INTERP_KERNEL::Exception("MEDCouplingCartesianAMRMesh::createPatchesFromCriterion : the criterion DataArrayByte instance must be allocated and not NULL !");
+    throw INTERP_KERNEL::Exception("MEDCouplingCartesianAMRMeshGen::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()
-{
-  _patches.clear();
-  declareAsNew();
-}
-
-void MEDCouplingCartesianAMRMeshGen::removePatch(int patchId)
-{
-  checkPatchId(patchId);
-  int sz((int)_patches.size()),j(0);
-  std::vector< MEDCouplingAutoRefCountObjectPtr<MEDCouplingCartesianAMRPatch> > patches(sz-1);
-  for(int i=0;i<sz;i++)
-    if(i!=patchId)
-      patches[j++]=_patches[i];
-  (const_cast<MEDCouplingCartesianAMRMeshGen *>(_patches[patchId]->getMesh()))->detachFromFather();
-  _patches=patches;
-  declareAsNew();
-}
-
-int MEDCouplingCartesianAMRMeshGen::getNumberOfPatches() const
+void MEDCouplingCartesianAMRMeshGen::createPatchesFromCriterion(const INTERP_KERNEL::BoxSplittingOptions& bso, const DataArrayDouble *criterion, const std::vector<int>& factors, double eps)
 {
-  return (int)_patches.size();
+  if(!criterion)
+    throw INTERP_KERNEL::Exception("MEDCouplingCartesianAMRMeshGen::createPatchesFromCriterion : null criterion pointer !");
+  std::vector<bool> inp(criterion->toVectorOfBool(eps));
+  createPatchesFromCriterion(bso,inp,factors);
 }
 
 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++)
+  for(std::vector< MCAuto<MEDCouplingCartesianAMRPatch> >::const_iterator it=_patches.begin();it!=_patches.end();it++,ret++)
     {
       if((*it)->getMesh()==mesh)
         return ret;
@@ -1096,7 +1167,7 @@ const MEDCouplingCartesianAMRPatch *MEDCouplingCartesianAMRMeshGen::getPatch(int
 bool MEDCouplingCartesianAMRMeshGen::isPatchInNeighborhoodOf(int patchId1, int patchId2, int ghostLev) const
 {
   const MEDCouplingCartesianAMRPatch *p1(getPatch(patchId1)),*p2(getPatch(patchId2));
-  return p1->isInMyNeighborhood(p2,GetGhostLevelInFineRef(ghostLev,_factors));
+  return p1->isInMyNeighborhood(p2,ghostLev);
 }
 
 /*!
@@ -1118,7 +1189,7 @@ DataArrayDouble *MEDCouplingCartesianAMRMeshGen::createCellFieldOnPatch(int patc
     throw INTERP_KERNEL::Exception("MEDCouplingCartesianAMRMesh::createCellFieldOnPatch : the input cell field array is NULL or not allocated !");
   const MEDCouplingCartesianAMRPatch *patch(getPatch(patchId));
   const MEDCouplingIMesh *fine(patch->getMesh()->getImageMesh());
-  MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> ret(DataArrayDouble::New()); ret->alloc(fine->getNumberOfCells(),cellFieldOnThis->getNumberOfComponents());
+  MCAuto<DataArrayDouble> ret(DataArrayDouble::New()); ret->alloc(fine->getNumberOfCells(),cellFieldOnThis->getNumberOfComponents());
   ret->copyStringInfoFrom(*cellFieldOnThis);
   MEDCouplingIMesh::SpreadCoarseToFine(cellFieldOnThis,_mesh->getCellGridStructure(),ret,patch->getBLTRRange(),getFactors());
   return ret.retn();
@@ -1134,12 +1205,17 @@ DataArrayDouble *MEDCouplingCartesianAMRMeshGen::createCellFieldOnPatch(int patc
  *
  * \sa createCellFieldOnPatch, fillCellFieldComingFromPatch
  */
-void MEDCouplingCartesianAMRMeshGen::fillCellFieldOnPatch(int patchId, const DataArrayDouble *cellFieldOnThis, DataArrayDouble *cellFieldOnPatch) const
+void MEDCouplingCartesianAMRMeshGen::fillCellFieldOnPatch(int patchId, const DataArrayDouble *cellFieldOnThis, DataArrayDouble *cellFieldOnPatch, bool isConservative) const
 {
   if(!cellFieldOnThis || !cellFieldOnThis->isAllocated())
     throw INTERP_KERNEL::Exception("MEDCouplingCartesianAMRMesh::createCellFieldOnPatch : the input cell field array is NULL or not allocated !");
   const MEDCouplingCartesianAMRPatch *patch(getPatch(patchId));
   MEDCouplingIMesh::SpreadCoarseToFine(cellFieldOnThis,_mesh->getCellGridStructure(),cellFieldOnPatch,patch->getBLTRRange(),getFactors());
+  if(isConservative)
+    {
+      int fact(MEDCouplingStructuredMesh::DeduceNumberOfGivenStructure(getFactors()));
+      std::transform(cellFieldOnPatch->begin(),cellFieldOnPatch->end(),cellFieldOnPatch->getPointer(),std::bind2nd(std::multiplies<double>(),1./((double)fact)));
+    }
 }
 
 /*!
@@ -1153,12 +1229,17 @@ void MEDCouplingCartesianAMRMeshGen::fillCellFieldOnPatch(int patchId, const Dat
  *
  * \sa fillCellFieldOnPatch, fillCellFieldOnPatchGhostAdv
  */
-void MEDCouplingCartesianAMRMeshGen::fillCellFieldOnPatchGhost(int patchId, const DataArrayDouble *cellFieldOnThis, DataArrayDouble *cellFieldOnPatch, int ghostLev) const
+void MEDCouplingCartesianAMRMeshGen::fillCellFieldOnPatchGhost(int patchId, const DataArrayDouble *cellFieldOnThis, DataArrayDouble *cellFieldOnPatch, int ghostLev, bool isConservative) const
 {
   if(!cellFieldOnThis || !cellFieldOnThis->isAllocated())
     throw INTERP_KERNEL::Exception("MEDCouplingCartesianAMRMesh::createCellFieldOnPatchGhost : the input cell field array is NULL or not allocated !");
   const MEDCouplingCartesianAMRPatch *patch(getPatch(patchId));
   MEDCouplingIMesh::SpreadCoarseToFineGhost(cellFieldOnThis,_mesh->getCellGridStructure(),cellFieldOnPatch,patch->getBLTRRange(),getFactors(),ghostLev);
+  if(isConservative)
+    {
+      int fact(MEDCouplingStructuredMesh::DeduceNumberOfGivenStructure(getFactors()));
+      std::transform(cellFieldOnPatch->begin(),cellFieldOnPatch->end(),cellFieldOnPatch->getPointer(),std::bind2nd(std::multiplies<double>(),1./((double)fact)));
+    }
 }
 
 /*!
@@ -1190,7 +1271,7 @@ void MEDCouplingCartesianAMRMeshGen::fillCellFieldOnPatchOnlyOnGhostZone(int pat
  *
  * \sa fillCellFieldOnPatchOnlyGhostAdv
  */
-void MEDCouplingCartesianAMRMeshGen::fillCellFieldOnPatchGhostAdv(int patchId, const DataArrayDouble *cellFieldOnThis, int ghostLev, const std::vector<const DataArrayDouble *>& arrsOnPatches) const
+void MEDCouplingCartesianAMRMeshGen::fillCellFieldOnPatchGhostAdv(int patchId, const DataArrayDouble *cellFieldOnThis, int ghostLev, const std::vector<const DataArrayDouble *>& arrsOnPatches, bool isConservative) const
 {
   int nbp(getNumberOfPatches());
   if(nbp!=(int)arrsOnPatches.size())
@@ -1200,7 +1281,7 @@ void MEDCouplingCartesianAMRMeshGen::fillCellFieldOnPatchGhostAdv(int patchId, c
     }
   DataArrayDouble *theFieldToFill(const_cast<DataArrayDouble *>(arrsOnPatches[patchId]));
   // first, do as usual
-  fillCellFieldOnPatchGhost(patchId,cellFieldOnThis,theFieldToFill,ghostLev);
+  fillCellFieldOnPatchGhost(patchId,cellFieldOnThis,theFieldToFill,ghostLev,isConservative);
   fillCellFieldOnPatchOnlyGhostAdv(patchId,ghostLev,arrsOnPatches);
 }
 
@@ -1239,17 +1320,23 @@ void MEDCouplingCartesianAMRMeshGen::fillCellFieldOnPatchOnlyOnGhostZoneWith(int
  * \param [in] patchId - The id of the patch \a cellFieldOnThis has to be put on.
  * \param [in] cellFieldOnPatch - The array of the cell field on patch with id \a patchId.
  * \param [in,out] cellFieldOnThis The array of the cell field on \a this to be updated only on the part concerning the patch with id \a patchId.
+ * \param [in] isConservative - true if the field needs to be conserved. false if maximum principle has to be applied.
  *
  * \throw if \a patchId is not in [ 0 , \c this->getNumberOfPatches() )
  * \throw if \a cellFieldOnPatch is NULL or not allocated
  * \sa createCellFieldOnPatch, MEDCouplingIMesh::CondenseFineToCoarse,fillCellFieldComingFromPatchGhost
  */
-void MEDCouplingCartesianAMRMeshGen::fillCellFieldComingFromPatch(int patchId, const DataArrayDouble *cellFieldOnPatch, DataArrayDouble *cellFieldOnThis) const
+void MEDCouplingCartesianAMRMeshGen::fillCellFieldComingFromPatch(int patchId, const DataArrayDouble *cellFieldOnPatch, DataArrayDouble *cellFieldOnThis, bool isConservative) const
 {
   if(!cellFieldOnPatch || !cellFieldOnPatch->isAllocated())
       throw INTERP_KERNEL::Exception("MEDCouplingCartesianAMRMesh::fillCellFieldComingFromPatch : the input cell field array is NULL or not allocated !");
   const MEDCouplingCartesianAMRPatch *patch(getPatch(patchId));
   MEDCouplingIMesh::CondenseFineToCoarse(_mesh->getCellGridStructure(),cellFieldOnPatch,patch->getBLTRRange(),getFactors(),cellFieldOnThis);
+  if(!isConservative)
+    {
+      int fact(MEDCouplingStructuredMesh::DeduceNumberOfGivenStructure(getFactors()));
+      MEDCouplingStructuredMesh::MultiplyPartOf(_mesh->getCellGridStructure(),patch->getBLTRRange(),1./((double)fact),cellFieldOnThis);
+    }
 }
 
 /*!
@@ -1260,17 +1347,23 @@ void MEDCouplingCartesianAMRMeshGen::fillCellFieldComingFromPatch(int patchId, c
  * \param [in] cellFieldOnPatch - The array of the cell field on patch with id \a patchId.
  * \param [in,out] cellFieldOnThis The array of the cell field on \a this to be updated only on the part concerning the patch with id \a patchId.
  * \param [in] ghostLev The size of ghost zone (must be >= 0 !)
+ * \param [in] isConservative - true if the field needs to be conserved. false if maximum principle has to be applied.
  *
  * \throw if \a patchId is not in [ 0 , \c this->getNumberOfPatches() )
  * \throw if \a cellFieldOnPatch is NULL or not allocated
  * \sa fillCellFieldComingFromPatch
  */
-void MEDCouplingCartesianAMRMeshGen::fillCellFieldComingFromPatchGhost(int patchId, const DataArrayDouble *cellFieldOnPatch, DataArrayDouble *cellFieldOnThis, int ghostLev) const
+void MEDCouplingCartesianAMRMeshGen::fillCellFieldComingFromPatchGhost(int patchId, const DataArrayDouble *cellFieldOnPatch, DataArrayDouble *cellFieldOnThis, int ghostLev, bool isConservative) const
 {
   if(!cellFieldOnPatch || !cellFieldOnPatch->isAllocated())
     throw INTERP_KERNEL::Exception("MEDCouplingCartesianAMRMesh::fillCellFieldComingFromPatchGhost : the input cell field array is NULL or not allocated !");
   const MEDCouplingCartesianAMRPatch *patch(getPatch(patchId));
   MEDCouplingIMesh::CondenseFineToCoarseGhost(_mesh->getCellGridStructure(),cellFieldOnPatch,patch->getBLTRRange(),getFactors(),cellFieldOnThis,ghostLev);
+  if(!isConservative)
+    {
+      int fact(MEDCouplingStructuredMesh::DeduceNumberOfGivenStructure(getFactors()));
+      MEDCouplingStructuredMesh::MultiplyPartOfByGhost(_mesh->getCellGridStructure(),patch->getBLTRRange(),ghostLev,1./((double)fact),cellFieldOnThis);
+    }
 }
 
 /*!
@@ -1284,7 +1377,7 @@ void MEDCouplingCartesianAMRMeshGen::fillCellFieldComingFromPatchGhost(int patch
 DataArrayInt *MEDCouplingCartesianAMRMeshGen::findPatchesInTheNeighborhoodOf(int patchId, int ghostLev) const
 {
   int nbp(getNumberOfPatches());
-  MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret(DataArrayInt::New()); ret->alloc(0,1);
+  MCAuto<DataArrayInt> ret(DataArrayInt::New()); ret->alloc(0,1);
   for(int i=0;i<nbp;i++)
     {
       if(i!=patchId)
@@ -1296,17 +1389,17 @@ DataArrayInt *MEDCouplingCartesianAMRMeshGen::findPatchesInTheNeighborhoodOf(int
 
 MEDCouplingUMesh *MEDCouplingCartesianAMRMeshGen::buildUnstructured() const
 {
-  MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> part(_mesh->buildUnstructured());
+  MCAuto<MEDCouplingUMesh> part(_mesh->buildUnstructured());
   std::vector<bool> bs(_mesh->getNumberOfCells(),false);
   std::vector<int> cgs(_mesh->getCellGridStructure());
-  std::vector< MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> > msSafe(_patches.size()+1);
+  std::vector< MCAuto<MEDCouplingUMesh> > msSafe(_patches.size()+1);
   std::size_t ii(0);
-  for(std::vector< MEDCouplingAutoRefCountObjectPtr<MEDCouplingCartesianAMRPatch> >::const_iterator it=_patches.begin();it!=_patches.end();it++,ii++)
+  for(std::vector< MCAuto<MEDCouplingCartesianAMRPatch> >::const_iterator it=_patches.begin();it!=_patches.end();it++,ii++)
     {
       MEDCouplingStructuredMesh::SwitchOnIdsFrom(cgs,(*it)->getBLTRRange(),bs);
       msSafe[ii+1]=(*it)->getMesh()->buildUnstructured();
     }
-  MEDCouplingAutoRefCountObjectPtr<DataArrayInt> eltsOff(DataArrayInt::BuildListOfSwitchedOff(bs));
+  MCAuto<DataArrayInt> eltsOff(DataArrayInt::BuildListOfSwitchedOff(bs));
   msSafe[0]=static_cast<MEDCouplingUMesh *>(part->buildPartOfMySelf(eltsOff->begin(),eltsOff->end(),false));
   std::vector< const MEDCouplingUMesh * > ms(msSafe.size());
   for(std::size_t i=0;i<msSafe.size();i++)
@@ -1323,14 +1416,14 @@ MEDCouplingUMesh *MEDCouplingCartesianAMRMeshGen::buildUnstructured() const
 MEDCoupling1SGTUMesh *MEDCouplingCartesianAMRMeshGen::buildMeshFromPatchEnvelop() const
 {
   std::vector<const MEDCoupling1SGTUMesh *> cells;
-  std::vector< MEDCouplingAutoRefCountObjectPtr<MEDCoupling1SGTUMesh> > cellsSafe;
-  for(std::vector< MEDCouplingAutoRefCountObjectPtr<MEDCouplingCartesianAMRPatch> >::const_iterator it=_patches.begin();it!=_patches.end();it++)
+  std::vector< MCAuto<MEDCoupling1SGTUMesh> > cellsSafe;
+  for(std::vector< MCAuto<MEDCouplingCartesianAMRPatch> >::const_iterator it=_patches.begin();it!=_patches.end();it++)
     {
       const MEDCouplingCartesianAMRPatch *patch(*it);
       if(patch)
         {
-          MEDCouplingAutoRefCountObjectPtr<MEDCouplingIMesh> cell(patch->getMesh()->getImageMesh()->asSingleCell());
-          MEDCouplingAutoRefCountObjectPtr<MEDCoupling1SGTUMesh> cell1SGT(cell->build1SGTUnstructured());
+          MCAuto<MEDCouplingIMesh> cell(patch->getMesh()->getImageMesh()->asSingleCell());
+          MCAuto<MEDCoupling1SGTUMesh> cell1SGT(cell->build1SGTUnstructured());
           cellsSafe.push_back(cell1SGT); cells.push_back(cell1SGT);
         }
     }
@@ -1340,13 +1433,13 @@ MEDCoupling1SGTUMesh *MEDCouplingCartesianAMRMeshGen::buildMeshFromPatchEnvelop(
 MEDCoupling1SGTUMesh *MEDCouplingCartesianAMRMeshGen::buildMeshOfDirectChildrenOnly() const
 {
   std::vector<const MEDCoupling1SGTUMesh *> patches;
-  std::vector< MEDCouplingAutoRefCountObjectPtr<MEDCoupling1SGTUMesh> > patchesSafe;
-  for(std::vector< MEDCouplingAutoRefCountObjectPtr<MEDCouplingCartesianAMRPatch> >::const_iterator it=_patches.begin();it!=_patches.end();it++)
+  std::vector< MCAuto<MEDCoupling1SGTUMesh> > patchesSafe;
+  for(std::vector< MCAuto<MEDCouplingCartesianAMRPatch> >::const_iterator it=_patches.begin();it!=_patches.end();it++)
       {
         const MEDCouplingCartesianAMRPatch *patch(*it);
         if(patch)
           {
-            MEDCouplingAutoRefCountObjectPtr<MEDCoupling1SGTUMesh> patchMesh(patch->getMesh()->getImageMesh()->build1SGTUnstructured());
+            MCAuto<MEDCoupling1SGTUMesh> patchMesh(patch->getMesh()->getImageMesh()->build1SGTUnstructured());
             patchesSafe.push_back(patchMesh); patches.push_back(patchMesh);
           }
       }
@@ -1365,23 +1458,23 @@ MEDCouplingFieldDouble *MEDCouplingCartesianAMRMeshGen::buildCellFieldOnRecurseW
   //
   std::vector<bool> bs(_mesh->getNumberOfCells(),false);
   std::vector<int> cgs(_mesh->getCellGridStructure());
-  std::vector< MEDCouplingAutoRefCountObjectPtr<MEDCouplingFieldDouble> > msSafe(_patches.size()+1);
+  std::vector< MCAuto<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++)
+  for(std::vector< MCAuto<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));
+  MCAuto<DataArrayInt> eltsOff(DataArrayInt::BuildListOfSwitchedOff(bs));
   //
-  MEDCouplingAutoRefCountObjectPtr<MEDCouplingFieldDouble> ret(MEDCouplingFieldDouble::New(ON_CELLS));
-  MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> arr2(extractGhostFrom(ghostSz,recurseArrs[0]));
+  MCAuto<MEDCouplingFieldDouble> ret(MEDCouplingFieldDouble::New(ON_CELLS));
+  MCAuto<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));
+  MCAuto<MEDCouplingUMesh> part(_mesh->buildUnstructured());
+  MCAuto<MEDCouplingMesh> mesh(part->buildPartOfMySelf(eltsOff->begin(),eltsOff->end(),false));
   ret->setMesh(mesh);
   msSafe[0]=ret;
   //
@@ -1401,8 +1494,8 @@ DataArrayDouble *MEDCouplingCartesianAMRMeshGen::extractGhostFrom(int ghostSz, c
   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));
+  MEDCouplingStructuredMesh::ApplyGhostOnCompactFrmt(p,ghostSz);
+  MCAuto<DataArrayDouble> ret(MEDCouplingStructuredMesh::ExtractFieldOfDoubleFrom(st,arr,p));
   return ret.retn();
 }
 
@@ -1425,19 +1518,52 @@ std::vector<int> MEDCouplingCartesianAMRMeshGen::getPatchIdsInTheNeighborhoodOf(
   return ret;
 }
 
+/*!
+ * This method returns a dump python of \a this. It is useful for users of createPatchesFromCriterion method for debugging.
+ *
+ * \sa dumpPatchesOf, createPatchesFromCriterion, createPatchesFromCriterionML
+ */
+std::string MEDCouplingCartesianAMRMeshGen::buildPythonDumpOfThis() const
+{
+  std::ostringstream oss;
+  oss << "amr=MEDCouplingCartesianAMRMesh(\""<< getImageMesh()->getName() << "\"," << getSpaceDimension() << ",[";
+  std::vector<int> ngs(getImageMesh()->getNodeGridStructure());
+  std::vector<double> orig(getImageMesh()->getOrigin()),dxyz(getImageMesh()->getDXYZ());
+  std::copy(ngs.begin(),ngs.end(),std::ostream_iterator<int>(oss,","));
+  oss <<  "],[";
+  std::copy(orig.begin(),orig.end(),std::ostream_iterator<double>(oss,","));
+  oss << "],[";
+  std::copy(dxyz.begin(),dxyz.end(),std::ostream_iterator<double>(oss,","));
+  oss << "])\n";
+  dumpPatchesOf("amr",oss);
+  return oss.str();
+}
+
+MEDCouplingCartesianAMRMeshGen::MEDCouplingCartesianAMRMeshGen(const MEDCouplingCartesianAMRMeshGen& other):RefCountObject(other),_mesh(other._mesh),_patches(other._patches),_factors(other._factors)
+{
+  const MEDCouplingIMesh *mesh(other._mesh);
+  if(mesh)
+    _mesh=static_cast<MEDCouplingIMesh *>(mesh->deepCopy());
+  std::size_t sz(other._patches.size());
+  for(std::size_t i=0;i<sz;i++)
+    {
+      const MEDCouplingCartesianAMRPatch *patch(other._patches[i]);
+      if(patch)
+        _patches[i]=patch->deepCopy(this);
+    }
+}
+
 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)
+                                                               const double *originStart, const double *originStop, const double *dxyzStart, const double *dxyzStop)
 {
   _mesh=MEDCouplingIMesh::New(meshName,spaceDim,nodeStrctStart,nodeStrctStop,originStart,originStop,dxyzStart,dxyzStop);
 }
 
-MEDCouplingCartesianAMRMeshGen::MEDCouplingCartesianAMRMeshGen(MEDCouplingCartesianAMRMeshGen *father, MEDCouplingIMesh *mesh):_father(father)
+MEDCouplingCartesianAMRMeshGen::MEDCouplingCartesianAMRMeshGen(MEDCouplingIMesh *mesh)
 {
-  if(!_father)
-    throw INTERP_KERNEL::Exception("MEDCouplingCartesianAMRMeshGen(MEDCouplingIMesh *mesh) constructor : empty father !");
   if(!mesh)
     throw INTERP_KERNEL::Exception("MEDCouplingCartesianAMRMeshGen(MEDCouplingIMesh *mesh) constructor : The input mesh is null !");
-  mesh->checkCoherency();
+  mesh->checkConsistencyLight();
   _mesh=mesh; _mesh->incrRef();
 }
 
@@ -1466,29 +1592,29 @@ void MEDCouplingCartesianAMRMeshGen::checkFactorsAndIfNotSetAssign(const std::ve
     }
 }
 
-void MEDCouplingCartesianAMRMeshGen::retrieveGridsAtInternal(int lev, std::vector< MEDCouplingAutoRefCountObjectPtr<MEDCouplingCartesianAMRPatchGen> >& grids) const
+void MEDCouplingCartesianAMRMeshGen::retrieveGridsAtInternal(int lev, std::vector< MCAuto<MEDCouplingCartesianAMRPatchGen> >& grids) const
 {
   if(lev==0)
     {
       const MEDCouplingCartesianAMRMesh *thisc(dynamic_cast<const MEDCouplingCartesianAMRMesh *>(this));//tony
-      MEDCouplingAutoRefCountObjectPtr<MEDCouplingCartesianAMRPatchGF> elt(new MEDCouplingCartesianAMRPatchGF(const_cast<MEDCouplingCartesianAMRMesh *>(thisc)));
+      MCAuto<MEDCouplingCartesianAMRPatchGF> elt(new MEDCouplingCartesianAMRPatchGF(const_cast<MEDCouplingCartesianAMRMesh *>(thisc)));
       grids.push_back(DynamicCastSafe<MEDCouplingCartesianAMRPatchGF,MEDCouplingCartesianAMRPatchGen>(elt));
     }
   else if(lev==1)
     {
-      for(std::vector< MEDCouplingAutoRefCountObjectPtr<MEDCouplingCartesianAMRPatch> >::const_iterator it=_patches.begin();it!=_patches.end();it++)
+      for(std::vector< MCAuto<MEDCouplingCartesianAMRPatch> >::const_iterator it=_patches.begin();it!=_patches.end();it++)
         {
           const MEDCouplingCartesianAMRPatch *pt(*it);
           if(pt)
             {
-              MEDCouplingAutoRefCountObjectPtr<MEDCouplingCartesianAMRPatch> tmp1(*it);
+              MCAuto<MEDCouplingCartesianAMRPatch> tmp1(*it);
               grids.push_back(DynamicCastSafe<MEDCouplingCartesianAMRPatch,MEDCouplingCartesianAMRPatchGen>(tmp1));
             }
         }
     }
   else
     {
-      for(std::vector< MEDCouplingAutoRefCountObjectPtr<MEDCouplingCartesianAMRPatch> >::const_iterator it=_patches.begin();it!=_patches.end();it++)
+      for(std::vector< MCAuto<MEDCouplingCartesianAMRPatch> >::const_iterator it=_patches.begin();it!=_patches.end();it++)
         {
           const MEDCouplingCartesianAMRPatch *pt(*it);
           if(pt)
@@ -1547,21 +1673,44 @@ std::vector<const DataArrayDouble *> MEDCouplingCartesianAMRMeshGen::extractSubT
   return ret;
 }
 
+void MEDCouplingCartesianAMRMeshGen::dumpPatchesOf(const std::string& varName, std::ostream& oss) const
+{
+  std::size_t j(0);
+  for(std::vector< MCAuto<MEDCouplingCartesianAMRPatch> >::const_iterator it=_patches.begin();it!=_patches.end();it++)
+    {
+      const MEDCouplingCartesianAMRPatch *patch(*it);
+      if(patch)
+        {
+          std::ostringstream oss2; oss2 << varName << ".addPatch([";
+          const std::vector< std::pair<int,int> >& bltr(patch->getBLTRRange());
+          std::size_t sz(bltr.size());
+          for(std::size_t i=0;i<sz;i++)
+            {
+              oss2 << "(" << bltr[i].first << "," << bltr[i].second << ")";
+              if(i!=sz-1)
+                oss2 << ",";
+            }
+          oss2 << "],[";
+          std::copy(_factors.begin(),_factors.end(),std::ostream_iterator<int>(oss2,","));
+          oss2 << "])\n";
+          oss << oss2.str();
+          std::ostringstream oss3; oss3 << varName << "[" << j++ << "]";
+          patch->getMesh()->dumpPatchesOf(oss3.str(),oss);
+        }
+    }
+}
+
 std::size_t MEDCouplingCartesianAMRMeshGen::getHeapMemorySizeWithoutChildren() const
 {
   return sizeof(MEDCouplingCartesianAMRMeshGen);
 }
 
-std::vector<const BigMemoryObject *> MEDCouplingCartesianAMRMeshGen::getDirectChildren() const
+std::vector<const BigMemoryObject *> MEDCouplingCartesianAMRMeshGen::getDirectChildrenWithNull() const
 {
   std::vector<const BigMemoryObject *> ret;
-  if((const MEDCouplingIMesh *)_mesh)
-    ret.push_back((const MEDCouplingIMesh *)_mesh);
-  for(std::vector< MEDCouplingAutoRefCountObjectPtr<MEDCouplingCartesianAMRPatch> >::const_iterator it=_patches.begin();it!=_patches.end();it++)
-    {
-      if((const MEDCouplingCartesianAMRPatch*)*it)
-        ret.push_back((const MEDCouplingCartesianAMRPatch*)*it);
-    }
+  ret.push_back((const MEDCouplingIMesh *)_mesh);
+  for(std::vector< MCAuto<MEDCouplingCartesianAMRPatch> >::const_iterator it=_patches.begin();it!=_patches.end();it++)
+    ret.push_back((const MEDCouplingCartesianAMRPatch*)*it);
   return ret;
 }
 
@@ -1569,7 +1718,7 @@ void MEDCouplingCartesianAMRMeshGen::updateTime() const
 {
   if((const MEDCouplingIMesh *)_mesh)
     updateTimeWith(*_mesh);
-  for(std::vector< MEDCouplingAutoRefCountObjectPtr<MEDCouplingCartesianAMRPatch> >::const_iterator it=_patches.begin();it!=_patches.end();it++)
+  for(std::vector< MCAuto<MEDCouplingCartesianAMRPatch> >::const_iterator it=_patches.begin();it!=_patches.end();it++)
     {
       const MEDCouplingCartesianAMRPatch *elt(*it);
       if(!elt)
@@ -1580,8 +1729,109 @@ void MEDCouplingCartesianAMRMeshGen::updateTime() const
     }
 }
 
-MEDCouplingCartesianAMRMeshSub::MEDCouplingCartesianAMRMeshSub(MEDCouplingCartesianAMRMeshGen *father, MEDCouplingIMesh *mesh):MEDCouplingCartesianAMRMeshGen(father,mesh)
+MEDCouplingCartesianAMRMeshSub::MEDCouplingCartesianAMRMeshSub(MEDCouplingCartesianAMRMeshGen *father, MEDCouplingIMesh *mesh):MEDCouplingCartesianAMRMeshGen(mesh),_father(father)
+{
+  if(!_father)
+    throw INTERP_KERNEL::Exception("MEDCouplingCartesianAMRMeshSub(MEDCouplingCartesianAMRMeshGen *father, MEDCouplingIMesh *mesh) constructor : empty father !");
+}
+
+const MEDCouplingCartesianAMRMeshGen *MEDCouplingCartesianAMRMeshSub::getFather() const
+{
+  return _father;
+}
+
+const MEDCouplingCartesianAMRMeshGen *MEDCouplingCartesianAMRMeshSub::getGodFather() const
+{
+  if(!_father)
+    throw INTERP_KERNEL::Exception("MEDCouplingCartesianAMRMeshSub::getGodFather : Impossible to find a god father because there is a hole in chain !");
+  return _father->getGodFather();
+}
+
+/*!
+ * This method returns the level of \a this. 0 for god father. 1 for children of god father ...
+ */
+int MEDCouplingCartesianAMRMeshSub::getAbsoluteLevel() const
+{
+  if(!_father)
+    throw INTERP_KERNEL::Exception("MEDCouplingCartesianAMRMeshSub::getAbsoluteLevel : Impossible to find a god father because there is a hole in chain !");
+  return _father->getAbsoluteLevel()+1;
+}
+
+void MEDCouplingCartesianAMRMeshSub::detachFromFather()
+{
+  _father=0;
+  declareAsNew();
+}
+
+std::vector< std::pair<int,int> > MEDCouplingCartesianAMRMeshSub::positionRelativeToGodFather(std::vector<int>& st) const
+{
+  st=_father->getFactors();
+  std::size_t dim(st.size());
+  std::vector<int> prev(st);
+  int id(_father->getPatchIdFromChildMesh(this));
+  const MEDCouplingCartesianAMRPatch *p(_father->getPatch(id));
+  std::vector< std::pair<int,int> > ret(p->getBLTRRange());
+  std::vector<int> delta(MEDCouplingStructuredMesh::GetDimensionsFromCompactFrmt(ret)),start(dim);
+  std::transform(delta.begin(),delta.end(),prev.begin(),delta.begin(),std::multiplies<int>());
+  for(std::size_t i=0;i<dim;i++)
+    start[i]=ret[i].first;
+  std::transform(start.begin(),start.end(),prev.begin(),start.begin(),std::multiplies<int>());
+  const MEDCouplingCartesianAMRMeshGen *it(_father);
+  while(!dynamic_cast<const MEDCouplingCartesianAMRMesh *>(it))
+    {
+      const MEDCouplingCartesianAMRMeshSub *itc(static_cast<const MEDCouplingCartesianAMRMeshSub *>(it));
+      int id2(itc->_father->getPatchIdFromChildMesh(itc));
+      const MEDCouplingCartesianAMRPatch *p2(itc->_father->getPatch(id2));
+      const std::vector< std::pair<int,int> >& start2(p2->getBLTRRange());
+      std::vector<int> tmp(dim);
+      for(std::size_t i=0;i<dim;i++)
+        tmp[i]=start2[i].first;
+      //
+      prev=itc->_father->getFactors();
+      std::transform(st.begin(),st.end(),prev.begin(),st.begin(),std::multiplies<int>());
+      std::transform(st.begin(),st.end(),tmp.begin(),tmp.begin(),std::multiplies<int>());
+      std::transform(start.begin(),start.end(),tmp.begin(),start.begin(),std::plus<int>());
+      it=itc->_father;
+    }
+  for(std::size_t i=0;i<dim;i++)
+    {
+      ret[i].first=start[i];
+      ret[i].second=start[i]+delta[i];
+    }
+  return ret;
+}
+
+int MEDCouplingCartesianAMRMeshSub::getAbsoluteLevelRelativeTo(const MEDCouplingCartesianAMRMeshGen *ref) const
 {
+  if(this==ref)
+    return 0;
+  if(_father==0)
+    throw INTERP_KERNEL::Exception("MEDCouplingCartesianAMRMeshSub::getAbsoluteLevelRelativeTo : ref is not in the progeny of this !");
+  else
+    return _father->getAbsoluteLevelRelativeTo(ref)+1;
+}
+
+MEDCouplingCartesianAMRMeshSub::MEDCouplingCartesianAMRMeshSub(const MEDCouplingCartesianAMRMeshSub& other, MEDCouplingCartesianAMRMeshGen *father):MEDCouplingCartesianAMRMeshGen(other),_father(father)
+{
+}
+
+MEDCouplingCartesianAMRMeshSub *MEDCouplingCartesianAMRMeshSub::deepCopy(MEDCouplingCartesianAMRMeshGen *fath) const
+{
+  return new MEDCouplingCartesianAMRMeshSub(*this,fath);
+}
+
+/*!
+ * \sa getPositionRelativeTo
+ */
+void MEDCouplingCartesianAMRMeshSub::getPositionRelativeToInternal(const MEDCouplingCartesianAMRMeshGen *ref, std::vector<int>& ret) const
+{
+  if(this==ref)
+    return ;
+  if(!_father)
+    throw INTERP_KERNEL::Exception("MEDCouplingCartesianAMRMeshSub::getPositionRelativeToInternal : ref is not in the progeny of this !");
+  int myId(_father->getPatchIdFromChildMesh(this));
+  ret.push_back(myId);
+  _father->getPositionRelativeToInternal(ref,ret);
 }
 
 MEDCouplingCartesianAMRMesh *MEDCouplingCartesianAMRMesh::New(const std::string& meshName, int spaceDim, const int *nodeStrctStart, const int *nodeStrctStop,
@@ -1590,28 +1840,122 @@ MEDCouplingCartesianAMRMesh *MEDCouplingCartesianAMRMesh::New(const std::string&
   return new MEDCouplingCartesianAMRMesh(meshName,spaceDim,nodeStrctStart,nodeStrctStop,originStart,originStop,dxyzStart,dxyzStop);
 }
 
-void MEDCouplingCartesianAMRMesh::setData(MEDCouplingDataForGodFather *data)
+MEDCouplingCartesianAMRMesh *MEDCouplingCartesianAMRMesh::New(MEDCouplingIMesh *mesh)
+{
+  return new MEDCouplingCartesianAMRMesh(mesh);
+}
+
+const MEDCouplingCartesianAMRMeshGen *MEDCouplingCartesianAMRMesh::getFather() const
+{
+  //I'm god father ! No father !
+  return 0;
+}
+
+const MEDCouplingCartesianAMRMeshGen *MEDCouplingCartesianAMRMesh::getGodFather() const
+{
+  return this;
+}
+
+int MEDCouplingCartesianAMRMesh::getAbsoluteLevel() const
+{
+  return 0;
+}
+
+void MEDCouplingCartesianAMRMesh::detachFromFather()
+{//not a bug - do nothing
+}
+
+std::vector< std::pair<int,int> > MEDCouplingCartesianAMRMesh::positionRelativeToGodFather(std::vector<int>& st) const
+{
+  st=_mesh->getCellGridStructure();
+  return MEDCouplingStructuredMesh::GetCompactFrmtFromDimensions(st);
+}
+
+int MEDCouplingCartesianAMRMesh::getAbsoluteLevelRelativeTo(const MEDCouplingCartesianAMRMeshGen *ref) const
+{
+  if(this==ref)
+    return 0;
+  throw INTERP_KERNEL::Exception("MEDCouplingCartesianAMRMesh::getAbsoluteLevelRelativeTo : ref is not in the progeny of this !");
+}
+
+std::vector<MEDCouplingCartesianAMRPatchGen *> MEDCouplingCartesianAMRMesh::retrieveGridsAt(int absoluteLev) const
 {
-  MEDCouplingDataForGodFather *myData(_data);
-  if(myData==data)
+  std::vector< MCAuto<MEDCouplingCartesianAMRPatchGen> > rets;
+  retrieveGridsAtInternal(absoluteLev,rets);
+  std::vector< MEDCouplingCartesianAMRPatchGen * > ret(rets.size());
+  for(std::size_t i=0;i<rets.size();i++)
+    {
+      ret[i]=rets[i].retn();
+    }
+  return ret;
+}
+
+MEDCouplingCartesianAMRMesh *MEDCouplingCartesianAMRMesh::deepCopy(MEDCouplingCartesianAMRMeshGen *father) const
+{
+  if(father)
+    throw INTERP_KERNEL::Exception("MEDCouplingCartesianAMRMesh::deepCopy : specifying a not null father for a God Father object !");
+  return new MEDCouplingCartesianAMRMesh(*this);
+}
+
+/*!
+ * This method creates a multi level patches split at once.
+ * This method calls as times as size of \a bso createPatchesFromCriterion. Size of \a bso and size of \a factors must be the same !
+ * \b WARNING, after the call the number of levels in \a this is equal to bso.size() + 1 !
+ *
+ * \param [in] bso
+ * \param [in] criterion
+ * \param [in] factors
+ * \param [in] eps - See DataArrayDouble::toVectorOfBool for more information about the semantic of eps.
+ *
+ * \sa createPatchesFromCriterion
+ */
+void MEDCouplingCartesianAMRMesh::createPatchesFromCriterionML(const std::vector<const INTERP_KERNEL::BoxSplittingOptions *>& bso, const DataArrayDouble *criterion, const std::vector< std::vector<int> >& factors, double eps)
+{
+  std::size_t nbOfLevs(bso.size());
+  if(nbOfLevs!=factors.size())
+    throw INTERP_KERNEL::Exception("MEDCouplingCartesianAMRMesh::createPatchesFromCriterionML : size of vectors must be the same !");
+  if(nbOfLevs==0)
     return ;
-  if(myData)
-    myData->changeGodFather(0);
-  _data=data;
-  if(data)
-    data->incrRef();
+  if(!bso[0])
+    throw INTERP_KERNEL::Exception("MEDCouplingCartesianAMRMesh::createPatchesFromCriterionML : pointers in 1st arg must be not NULL !");
+  createPatchesFromCriterion(*bso[0],criterion,factors[0],eps);
+  for(std::size_t i=1;i<nbOfLevs;i++)
+    {
+      if(!bso[i])
+        throw INTERP_KERNEL::Exception("MEDCouplingCartesianAMRMesh::createPatchesFromCriterionML : presence of a NULL BoxSplittingOptions in input vector !");
+      //
+      std::vector<MEDCouplingCartesianAMRPatchGen *> elts(retrieveGridsAt((int)(i)));
+      std::size_t sz(elts.size());
+      std::vector< MCAuto<MEDCouplingCartesianAMRPatchGen> > elts2(sz);
+      std::vector< MCAuto<DataArrayDouble> > elts3(sz);
+      for(std::size_t ii=0;ii<sz;ii++)
+        elts2[ii]=elts[ii];
+      //
+      static const char TMP_STR[]="TMP";
+      std::vector< std::pair<std::string,int> > fieldNames(1); fieldNames[0].first=TMP_STR; fieldNames[0].second=1;
+      MCAuto<MEDCouplingAMRAttribute> att(MEDCouplingAMRAttribute::New(this,fieldNames,0));
+      att->alloc();
+      DataArrayDouble *tmpDa(const_cast<DataArrayDouble *>(att->getFieldOn(this,TMP_STR)));
+      tmpDa->deepCopyFrom(*criterion);
+      att->synchronizeCoarseToFine();
+      for(std::size_t ii=0;ii<sz;ii++)
+        {
+          const DataArrayDouble *critOnLeaf(att->getFieldOn(const_cast<MEDCouplingCartesianAMRMeshGen *>(elts[ii]->getMesh()),TMP_STR));
+          elts3[ii]=const_cast<DataArrayDouble *>(critOnLeaf); elts3[ii]->incrRef();
+        }
+      att=0;
+      for(std::size_t ii=0;ii<sz;ii++)
+        const_cast<MEDCouplingCartesianAMRMeshGen *>(elts[ii]->getMesh())->createPatchesFromCriterion(*bso[i],elts3[ii],factors[i],eps);
+    }
 }
 
-void MEDCouplingCartesianAMRMesh::allocData() const
+void MEDCouplingCartesianAMRMesh::getPositionRelativeToInternal(const MEDCouplingCartesianAMRMeshGen *ref, std::vector<int>& ret) const
 {
-  checkData();
-  _data->alloc();
+
 }
 
-void MEDCouplingCartesianAMRMesh::deallocData() const
+MEDCouplingCartesianAMRMesh::MEDCouplingCartesianAMRMesh(const MEDCouplingCartesianAMRMesh& other):MEDCouplingCartesianAMRMeshGen(other)
 {
-  checkData();
-  _data->dealloc();
 }
 
 MEDCouplingCartesianAMRMesh::MEDCouplingCartesianAMRMesh(const std::string& meshName, int spaceDim, const int *nodeStrctStart, const int *nodeStrctStop,
@@ -1619,25 +1963,16 @@ MEDCouplingCartesianAMRMesh::MEDCouplingCartesianAMRMesh(const std::string& mesh
 {
 }
 
-std::vector<const BigMemoryObject *> MEDCouplingCartesianAMRMesh::getDirectChildren() const
+MEDCouplingCartesianAMRMesh::MEDCouplingCartesianAMRMesh(MEDCouplingIMesh *mesh):MEDCouplingCartesianAMRMeshGen(mesh)
 {
-  std::vector<const BigMemoryObject *> ret(MEDCouplingCartesianAMRMeshGen::getDirectChildren());
-  const MEDCouplingDataForGodFather *pt(_data);
-  if(pt)
-    ret.push_back(pt);
-  return ret;
 }
 
-void MEDCouplingCartesianAMRMesh::checkData() const
+std::vector<const BigMemoryObject *> MEDCouplingCartesianAMRMesh::getDirectChildrenWithNull() const
 {
-  const MEDCouplingDataForGodFather *data(_data);
-  if(!data)
-    throw INTERP_KERNEL::Exception("MEDCouplingCartesianAMRMesh::checkData : no data set !");
+  std::vector<const BigMemoryObject *> ret(MEDCouplingCartesianAMRMeshGen::getDirectChildrenWithNull());
+  return ret;
 }
 
 MEDCouplingCartesianAMRMesh::~MEDCouplingCartesianAMRMesh()
 {
-  MEDCouplingDataForGodFather *data(_data);
-  if(data)
-    data->changeGodFather(0);
 }