Salome HOME
Prepare int64 management - example 3
[tools/medcoupling.git] / src / MEDCoupling / MEDCouplingCartesianAMRMesh.cxx
index ac1351238e5b50199a161828b1eb104612186a2e..d9722e0115f32d4e6b16b0f666692a74ae84f035 100644 (file)
@@ -1,4 +1,4 @@
-// Copyright (C) 2007-2014  CEA/DEN, EDF R&D
+// Copyright (C) 2007-2016  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,15 +372,20 @@ 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);
 }
 
 /*!
  * \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 !
- * This method has 3 outputs. 2 two first are the resp the position of \a p1 and \a p2 relative to \a p1. And \a factToApplyOn2 is the coeff of refinement to be applied on \a p2 to be virtualy
+ * This method has 3 outputs. 2 two first are the resp the position of \a p1 and \a p2 relative to \a p1. And \a factToApplyOn2 is the coeff of refinement to be applied on \a p2 to be virtually
  * on the same level as \a p1.
  */
 void MEDCouplingCartesianAMRPatch::ComputeZonesOfTwoRelativeToOneDiffLev(int ghostLev, const MEDCouplingCartesianAMRPatch *p1, const MEDCouplingCartesianAMRPatch *p2, std::vector< std::pair<int,int> >& p1Zone, std::vector< std::pair<int,int> >& p2Zone, std::vector<int>& factToApplyOn2)
@@ -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)
+std::size_t MEDCouplingCartesianAMRPatchGF::getHeapMemorySizeWithoutChildren() const
 {
-  if(!_gf)
-    throw INTERP_KERNEL::Exception("MEDCouplingDataForGodFather constructor : A data has to be attached to a AMR Mesh instance !");
-  _gf->setData(this);
+  return sizeof(MEDCouplingCartesianAMRPatchGF);
 }
 
-void MEDCouplingDataForGodFather::checkGodFatherFrozen() const
+MEDCouplingCartesianAMRPatchGF::MEDCouplingCartesianAMRPatchGF(const MEDCouplingCartesianAMRPatchGF& other, MEDCouplingCartesianAMRMeshGen *father):MEDCouplingCartesianAMRPatchGen(other,father)
 {
-  _tlc.checkConst();
-}
-
-bool MEDCouplingDataForGodFather::changeGodFather(MEDCouplingCartesianAMRMesh *gf)
-{
-  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,103 +980,147 @@ 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();
@@ -1047,34 +1134,10 @@ void MEDCouplingCartesianAMRMeshGen::createPatchesFromCriterion(const INTERP_KER
   createPatchesFromCriterion(bso,inp,factors);
 }
 
-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
-{
-  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++)
+  for(std::vector< MCAuto<MEDCouplingCartesianAMRPatch> >::const_iterator it=_patches.begin();it!=_patches.end();it++,ret++)
     {
       if((*it)->getMesh()==mesh)
         return ret;
@@ -1104,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);
 }
 
 /*!
@@ -1126,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();
@@ -1142,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)));
+    }
 }
 
 /*!
@@ -1161,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)));
+    }
 }
 
 /*!
@@ -1198,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())
@@ -1208,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);
 }
 
@@ -1247,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);
+    }
 }
 
 /*!
@@ -1268,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);
+    }
 }
 
 /*!
@@ -1292,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)
@@ -1304,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++)
@@ -1331,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);
         }
     }
@@ -1348,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);
           }
       }
@@ -1373,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;
   //
@@ -1409,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();
 }
 
@@ -1433,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();
 }
 
@@ -1474,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)
@@ -1555,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;
 }
 
@@ -1577,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)
@@ -1588,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,
@@ -1598,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,
@@ -1627,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);
 }