Salome HOME
Some debugs and improvements. Tests coming soon !
[modules/med.git] / src / MEDCoupling / MEDCouplingAMRAttribute.cxx
index e5701be79a55d43b0813ea6b02cf70422661c23f..9e601b98825c7f82d9bd5017fd52759315334cbe 100644 (file)
@@ -32,18 +32,23 @@ DataArrayDoubleCollection *DataArrayDoubleCollection::New(const std::vector< std
   return new DataArrayDoubleCollection(fieldNames);
 }
 
+DataArrayDoubleCollection *DataArrayDoubleCollection::deepCpy() const
+{
+  return new DataArrayDoubleCollection(*this);
+}
+
 void DataArrayDoubleCollection::allocTuples(int nbOfTuples)
 {
   std::size_t sz(_arrs.size());
   for(std::size_t i=0;i<sz;i++)
-    _arrs[i]->reAlloc(nbOfTuples);
+    _arrs[i].first->reAlloc(nbOfTuples);
 }
 
 void DataArrayDoubleCollection::dellocTuples()
 {
   std::size_t sz(_arrs.size());
   for(std::size_t i=0;i<sz;i++)
-    _arrs[i]->reAlloc(0);
+    _arrs[i].first->reAlloc(0);
 }
 
 void DataArrayDoubleCollection::spillInfoOnComponents(const std::vector< std::vector<std::string> >& compNames)
@@ -54,7 +59,19 @@ void DataArrayDoubleCollection::spillInfoOnComponents(const std::vector< std::ve
   for(std::size_t i=0;i<sz;i++)
     {
       const std::vector<std::string>& names(compNames[i]);
-      _arrs[i]->setInfoOnComponents(names);
+      _arrs[i].first->setInfoOnComponents(names);
+    }
+}
+
+void DataArrayDoubleCollection::spillNatures(const std::vector<NatureOfField>& nfs)
+{
+  std::size_t sz(_arrs.size());
+  if(sz!=nfs.size())
+    throw INTERP_KERNEL::Exception("DataArrayDoubleCollection::spillNatures : first size of vector of NatureOfField has to be equal to the number of fields defined !");
+  for(std::size_t i=0;i<sz;i++)
+    {
+      CheckValidNature(nfs[i]);
+      _arrs[i].second=nfs[i];
     }
 }
 
@@ -64,7 +81,7 @@ std::vector<DataArrayDouble *> DataArrayDoubleCollection::retrieveFields() const
   std::vector<DataArrayDouble *> ret(sz);
   for(std::size_t i=0;i<sz;i++)
     {
-      const DataArrayDouble *tmp(_arrs[i]);
+      const DataArrayDouble *tmp(_arrs[i].first);
       ret[i]=const_cast<DataArrayDouble *>(tmp);
       if(ret[i])
         ret[i]->incrRef();
@@ -75,9 +92,9 @@ std::vector<DataArrayDouble *> DataArrayDoubleCollection::retrieveFields() const
 const DataArrayDouble *DataArrayDoubleCollection::getFieldWithName(const std::string& name) const
 {
   std::vector<std::string> vec;
-  for(std::vector< MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> >::const_iterator it=_arrs.begin();it!=_arrs.end();it++)
+  for(std::vector< std::pair< MEDCouplingAutoRefCountObjectPtr<DataArrayDouble>, NatureOfField > >::const_iterator it=_arrs.begin();it!=_arrs.end();it++)
     {
-      const DataArrayDouble *obj(*it);
+      const DataArrayDouble *obj((*it).first);
       if(obj)
         {
           if(obj->getName()==name)
@@ -99,7 +116,10 @@ void DataArrayDoubleCollection::SynchronizeFineToCoarse(int ghostLev, const MEDC
   if(fine->_arrs.size()!=sz)
     throw INTERP_KERNEL::Exception("DataArrayDoubleCollection::SynchronizeFineToCoarse : the input DataArrayDouble collection must have the same size !");
   for(std::size_t i=0;i<sz;i++)
-    fatherOfFineMesh->fillCellFieldComingFromPatchGhost(patchId,fine->_arrs[i],coarse->_arrs[i],ghostLev);
+    {
+      CheckSameNatures(fine->_arrs[i].second,coarse->_arrs[i].second);
+      fatherOfFineMesh->fillCellFieldComingFromPatchGhost(patchId,fine->_arrs[i].first,coarse->_arrs[i].first,ghostLev,IsConservativeNature(coarse->_arrs[i].second));
+    }
 }
 
 void DataArrayDoubleCollection::SynchronizeCoarseToFine(int ghostLev, const MEDCouplingCartesianAMRMeshGen *fatherOfFineMesh, int patchId, const DataArrayDoubleCollection *coarse, DataArrayDoubleCollection *fine)
@@ -110,7 +130,10 @@ void DataArrayDoubleCollection::SynchronizeCoarseToFine(int ghostLev, const MEDC
   if(fine->_arrs.size()!=sz)
     throw INTERP_KERNEL::Exception("DataArrayDoubleCollection::SynchronizeCoarseToFine : the input DataArrayDouble collection must have the same size !");
   for(std::size_t i=0;i<sz;i++)
-    fatherOfFineMesh->fillCellFieldOnPatchGhost(patchId,coarse->_arrs[i],fine->_arrs[i],ghostLev);
+    {
+      CheckSameNatures(fine->_arrs[i].second,coarse->_arrs[i].second);
+      fatherOfFineMesh->fillCellFieldOnPatchGhost(patchId,coarse->_arrs[i].first,fine->_arrs[i].first,ghostLev,IsConservativeNature(coarse->_arrs[i].second));
+    }
 }
 
 void DataArrayDoubleCollection::SynchronizeFineEachOther(int patchId, int ghostLev, const MEDCouplingCartesianAMRMeshGen *fatherOfFineMesh, const std::vector<const MEDCouplingCartesianAMRMeshGen *>& children, const std::vector<DataArrayDoubleCollection *>& fieldsOnFine)
@@ -133,7 +156,7 @@ void DataArrayDoubleCollection::SynchronizeFineEachOther(int patchId, int ghostL
     {
       std::vector<const DataArrayDouble *> arrs(sz);
       for(std::size_t j=0;j<sz;j++)
-        arrs[j]=fieldsOnFine[j]->_arrs[i];
+        arrs[j]=fieldsOnFine[j]->_arrs[i].first;
       fatherOfFineMesh->fillCellFieldOnPatchOnlyGhostAdv(patchId,ghostLev,arrs);
     }
 }
@@ -150,8 +173,8 @@ void DataArrayDoubleCollection::SynchronizeGhostZoneOfOneUsingTwo(int ghostLev,
     throw INTERP_KERNEL::Exception("DataArrayDoubleCollection::SynchronizeGhostZoneOfOneUsingTwo : size of DataArrayDouble Collection must be the same !");
   for(std::size_t i=0;i<sz;i++)
     {
-      const DataArrayDouble *zeArrWhichGhostsWillBeUpdated(p1dac->_arrs[i]);
-      MEDCouplingCartesianAMRPatch::UpdateNeighborsOfOneWithTwoMixedLev(ghostLev,p1,p2,const_cast<DataArrayDouble *>(zeArrWhichGhostsWillBeUpdated),p2dac->_arrs[i]);
+      const DataArrayDouble *zeArrWhichGhostsWillBeUpdated(p1dac->_arrs[i].first);
+      MEDCouplingCartesianAMRPatch::UpdateNeighborsOfOneWithTwoMixedLev(ghostLev,p1,p2,const_cast<DataArrayDouble *>(zeArrWhichGhostsWillBeUpdated),p2dac->_arrs[i].first);
     }
 }
 
@@ -163,7 +186,7 @@ void DataArrayDoubleCollection::SynchronizeCoarseToFineOnlyInGhostZone(int ghost
   if(fine->_arrs.size()!=sz)
     throw INTERP_KERNEL::Exception("DataArrayDoubleCollection::SynchronizeCoarseToFineOnlyInGhostZone : the input DataArrayDouble collection must have the same size !");
   for(std::size_t i=0;i<sz;i++)
-    fatherOfFineMesh->fillCellFieldOnPatchOnlyOnGhostZone(patchId,coarse->_arrs[i],fine->_arrs[i],ghostLev);
+    fatherOfFineMesh->fillCellFieldOnPatchOnlyOnGhostZone(patchId,coarse->_arrs[i].first,fine->_arrs[i].first,ghostLev);
 }
 
 void DataArrayDoubleCollection::synchronizeMyGhostZoneUsing(int ghostLev, const DataArrayDoubleCollection& other, const MEDCouplingCartesianAMRPatch *thisp, const MEDCouplingCartesianAMRPatch *otherp, const MEDCouplingCartesianAMRMeshGen *father) const
@@ -173,7 +196,7 @@ void DataArrayDoubleCollection::synchronizeMyGhostZoneUsing(int ghostLev, const
   if(other._arrs.size()!=sz)
     throw INTERP_KERNEL::Exception("DataArrayDoubleCollection::synchronizeMyGhostZoneUsing : sizes of collections must match !");
   for(std::size_t i=0;i<sz;i++)
-    father->fillCellFieldOnPatchOnlyOnGhostZoneWith(ghostLev,thisp,otherp,thisNC->_arrs[i],other._arrs[i]);
+    father->fillCellFieldOnPatchOnlyOnGhostZoneWith(ghostLev,thisp,otherp,thisNC->_arrs[i].first,other._arrs[i].first);
 }
 
 void DataArrayDoubleCollection::synchronizeMyGhostZoneUsingExt(int ghostLev, const DataArrayDoubleCollection& other, const MEDCouplingCartesianAMRPatch *thisp, const MEDCouplingCartesianAMRPatch *otherp) const
@@ -183,7 +206,7 @@ void DataArrayDoubleCollection::synchronizeMyGhostZoneUsingExt(int ghostLev, con
   if(other._arrs.size()!=sz)
     throw INTERP_KERNEL::Exception("DataArrayDoubleCollection::synchronizeMyGhostZoneUsingExt : sizes of collections must match !");
   for(std::size_t i=0;i<sz;i++)
-    MEDCouplingCartesianAMRPatch::UpdateNeighborsOfOneWithTwoExt(ghostLev,thisp,otherp,thisNC->_arrs[i],other._arrs[i]);
+    MEDCouplingCartesianAMRPatch::UpdateNeighborsOfOneWithTwoExt(ghostLev,thisp,otherp,thisNC->_arrs[i].first,other._arrs[i].first);
 }
 
 DataArrayDoubleCollection::DataArrayDoubleCollection(const std::vector< std::pair<std::string,int> >& fieldNames):_arrs(fieldNames.size())
@@ -193,14 +216,27 @@ DataArrayDoubleCollection::DataArrayDoubleCollection(const std::vector< std::pai
   for(std::size_t i=0;i<sz;i++)
     {
       const std::pair<std::string,int>& info(fieldNames[i]);
-      _arrs[i]=DataArrayDouble::New();
-      _arrs[i]->alloc(0,info.second);
-      _arrs[i]->setName(info.first);
+      _arrs[i].first=DataArrayDouble::New();
+      _arrs[i].first->alloc(0,info.second);
+      _arrs[i].first->setName(info.first);
       names[i]=info.second;
+      _arrs[i].second=ConservativeVolumic;
     }
   CheckDiscriminantNames(names);
 }
 
+DataArrayDoubleCollection::DataArrayDoubleCollection(const DataArrayDoubleCollection& other):RefCountObject(other),_arrs(other._arrs.size())
+{
+  std::size_t sz(other._arrs.size());
+  for(std::size_t i=0;i<sz;i++)
+    {
+      _arrs[i].second=other._arrs[i].second;
+      const DataArrayDouble *da(other._arrs[i].first);
+      if(da)
+        _arrs[i].first=da->deepCpy();
+    }
+}
+
 std::size_t DataArrayDoubleCollection::getHeapMemorySizeWithoutChildren() const
 {
   std::size_t ret(sizeof(DataArrayDoubleCollection));
@@ -211,9 +247,9 @@ std::size_t DataArrayDoubleCollection::getHeapMemorySizeWithoutChildren() const
 std::vector<const BigMemoryObject *> DataArrayDoubleCollection::getDirectChildren() const
 {
   std::vector<const BigMemoryObject *> ret;
-  for(std::vector< MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> >::const_iterator it=_arrs.begin();it!=_arrs.end();it++)
+  for(std::vector< std::pair< MEDCouplingAutoRefCountObjectPtr<DataArrayDouble>, NatureOfField > >::const_iterator it=_arrs.begin();it!=_arrs.end();it++)
     {
-      const DataArrayDouble *pt(*it);
+      const DataArrayDouble *pt((*it).first);
       if(pt)
         ret.push_back(pt);
     }
@@ -222,9 +258,9 @@ std::vector<const BigMemoryObject *> DataArrayDoubleCollection::getDirectChildre
 
 void DataArrayDoubleCollection::updateTime() const
 {
-  for(std::vector< MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> >::const_iterator it=_arrs.begin();it!=_arrs.end();it++)
+  for(std::vector< std::pair< MEDCouplingAutoRefCountObjectPtr<DataArrayDouble>, NatureOfField > >::const_iterator it=_arrs.begin();it!=_arrs.end();it++)
     {
-      const DataArrayDouble *pt(*it);
+      const DataArrayDouble *pt((*it).first);
       if(pt)
         updateTimeWith(*pt);
     }
@@ -237,11 +273,36 @@ void DataArrayDoubleCollection::CheckDiscriminantNames(const std::vector<std::st
     throw INTERP_KERNEL::Exception("DataArrayDoubleCollection::CheckDiscriminantNames : The names of fields must be different each other ! It is not the case !");
 }
 
+bool DataArrayDoubleCollection::IsConservativeNature(NatureOfField n)
+{
+  CheckValidNature(n);
+  return n==RevIntegral || n==IntegralGlobConstraint;
+}
+
+void DataArrayDoubleCollection::CheckSameNatures(NatureOfField n1, NatureOfField n2)
+{
+  CheckValidNature(n1);
+  CheckValidNature(n2);
+  if(n1!=n2)
+    throw INTERP_KERNEL::Exception("DataArrayDoubleCollection::CheckSameNatures : natures are not the same !");
+}
+
+void DataArrayDoubleCollection::CheckValidNature(NatureOfField n)
+{
+  if(n!=ConservativeVolumic && n!=Integral && n!=IntegralGlobConstraint && n!=RevIntegral)
+    throw INTERP_KERNEL::Exception("DataArrayDoubleCollection::CheckValidNature : unrecognized nature !");
+}
+
 MEDCouplingGridCollection *MEDCouplingGridCollection::New(const std::vector<const MEDCouplingCartesianAMRMeshGen *>& ms, const std::vector< std::pair<std::string,int> >& fieldNames)
 {
   return new MEDCouplingGridCollection(ms,fieldNames);
 }
 
+MEDCouplingGridCollection *MEDCouplingGridCollection::deepCpy(const MEDCouplingCartesianAMRMeshGen *newGf, const MEDCouplingCartesianAMRMeshGen *oldGf) const
+{
+  return new MEDCouplingGridCollection(*this,newGf,oldGf);
+}
+
 void MEDCouplingGridCollection::alloc(int ghostLev)
 {
   for(std::vector< std::pair<const MEDCouplingCartesianAMRMeshGen *,MEDCouplingAutoRefCountObjectPtr<DataArrayDoubleCollection> > >::iterator it=_map_of_dadc.begin();it!=_map_of_dadc.end();it++)
@@ -273,6 +334,12 @@ void MEDCouplingGridCollection::spillInfoOnComponents(const std::vector< std::ve
     (*it).second->spillInfoOnComponents(compNames);
 }
 
+void MEDCouplingGridCollection::spillNatures(const std::vector<NatureOfField>& nfs)
+{
+  for(std::vector< std::pair<const MEDCouplingCartesianAMRMeshGen *,MEDCouplingAutoRefCountObjectPtr<DataArrayDoubleCollection> > >::iterator it=_map_of_dadc.begin();it!=_map_of_dadc.end();it++)
+    (*it).second->spillNatures(nfs);
+}
+
 bool MEDCouplingGridCollection::presenceOf(const MEDCouplingCartesianAMRMeshGen *m, int& pos) const
 {
   int ret(0);
@@ -472,6 +539,19 @@ MEDCouplingGridCollection::MEDCouplingGridCollection(const std::vector<const MED
     }
 }
 
+MEDCouplingGridCollection::MEDCouplingGridCollection(const MEDCouplingGridCollection& other, const MEDCouplingCartesianAMRMeshGen *newGf, const MEDCouplingCartesianAMRMeshGen *oldGf):RefCountObject(other),_map_of_dadc(other._map_of_dadc.size())
+{
+  std::size_t sz(other._map_of_dadc.size());
+  for(std::size_t i=0;i<sz;i++)
+    {
+      std::vector<int> pos(other._map_of_dadc[i].first->getPositionRelativeTo(oldGf));
+      _map_of_dadc[i].first=newGf->getMeshAtPosition(pos);
+      const DataArrayDoubleCollection *dac(other._map_of_dadc[i].second);
+      if(dac)
+        _map_of_dadc[i].second=dac->deepCpy();
+    }
+}
+
 std::size_t MEDCouplingGridCollection::getHeapMemorySizeWithoutChildren() const
 {
   std::size_t ret(sizeof(MEDCouplingGridCollection));
@@ -504,6 +584,47 @@ void MEDCouplingGridCollection::updateTime() const
     }
 }
 
+MEDCouplingCartesianAMRMesh *MEDCouplingDataForGodFather::getMyGodFather()
+{
+  return _gf;
+}
+
+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->incrRef();
+}
+
+void MEDCouplingDataForGodFather::checkGodFatherFrozen() const
+{
+  _tlc.checkConst();
+}
+
+bool MEDCouplingDataForGodFather::changeGodFather(MEDCouplingCartesianAMRMesh *gf)
+{
+  bool ret(_tlc.keepTrackOfNewTL(gf));
+  if(ret)
+    {
+      _gf=gf;
+      if(gf)
+        gf->incrRef();
+    }
+  return ret;
+}
+
+MEDCouplingDataForGodFather::MEDCouplingDataForGodFather(const MEDCouplingDataForGodFather& other, bool deepCpyGF):RefCountObject(other),_gf(other._gf),_tlc(other._gf)
+{
+  other._tlc.checkConst();
+  if(deepCpyGF)
+    {
+      const MEDCouplingCartesianAMRMesh *gf(other._gf);
+      if(gf)
+        _gf=gf->deepCpy(0);
+      _tlc.keepTrackOfNewTL(_gf);
+    }
+}
+
 /*!
  * This method creates, attach to a main AMR mesh \a gf ( called god father :-) ) and returns a data linked to \a gf ready for the computation.
  */
@@ -541,6 +662,37 @@ void MEDCouplingAMRAttribute::spillInfoOnComponents(const std::vector< std::vect
     (*it)->spillInfoOnComponents(compNames);
 }
 
+/*!
+ * Assign nature for each fields in \a this.
+ * \param [in] nfs
+ */
+void MEDCouplingAMRAttribute::spillNatures(const std::vector<NatureOfField>& nfs)
+{
+  _tlc.checkConst();
+  for(std::vector< MEDCouplingAutoRefCountObjectPtr<MEDCouplingGridCollection> >::iterator it=_levs.begin();it!=_levs.end();it++)
+    (*it)->spillNatures(nfs);
+}
+
+MEDCouplingAMRAttribute *MEDCouplingAMRAttribute::deepCpy() const
+{
+  return new MEDCouplingAMRAttribute(*this,true);
+}
+
+MEDCouplingAMRAttribute *MEDCouplingAMRAttribute::deepCpyWithoutGodFather() const
+{
+  return new MEDCouplingAMRAttribute(*this,false);
+}
+
+/*!
+ * Returns the number of levels by \b only \b considering \a this (god father instance is considered only to see if it has not changed still last update of \a this).
+ *
+ */
+int MEDCouplingAMRAttribute::getNumberOfLevels() const
+{
+  checkGodFatherFrozen();
+  return (int)_levs.size();
+}
+
 /*!
  * This method returns all DataArrayDouble instances lying on the specified mesh \a mesh.
  * If \a mesh is not part of the progeny of god father object given at construction of \a this an exception will be thrown.
@@ -614,6 +766,7 @@ MEDCouplingFieldDouble *MEDCouplingAMRAttribute::buildCellFieldOnRecurseWithoutO
  *
  * \return MEDCouplingFieldDouble * - a field on cells that the caller has to deal with (deallocate it).
  *
+ * \sa buildCellFieldOnWithoutGhost
  */
 MEDCouplingFieldDouble *MEDCouplingAMRAttribute::buildCellFieldOnWithGhost(MEDCouplingCartesianAMRMeshGen *mesh, const std::string& fieldName) const
 {
@@ -637,9 +790,53 @@ MEDCouplingFieldDouble *MEDCouplingAMRAttribute::buildCellFieldOnWithGhost(MEDCo
   return ret.retn();
 }
 
+/*!
+ * This method builds a newly created field on cell just lying on mesh \a mesh without its eventual refinement.
+ * The output field does not display ghost cells.
+ *
+ * \return MEDCouplingFieldDouble * - a field on cells that the caller has to deal with (deallocate it).
+ *
+ * \sa buildCellFieldOnWithGhost
+ */
+MEDCouplingFieldDouble *MEDCouplingAMRAttribute::buildCellFieldOnWithoutGhost(MEDCouplingCartesianAMRMeshGen *mesh, const std::string& fieldName) const
+{
+  //tony
+  const DataArrayDouble *arr(0);
+  for(std::vector< MEDCouplingAutoRefCountObjectPtr<MEDCouplingGridCollection> >::const_iterator it=_levs.begin();it!=_levs.end();it++)
+    {
+      int tmp(-1);
+      if((*it)->presenceOf(mesh,tmp))
+        {
+          const DataArrayDoubleCollection& ddc((*it)->getFieldsAt(tmp));
+          arr=ddc.getFieldWithName(fieldName);
+        }
+    }
+  if(!arr)
+    throw INTERP_KERNEL::Exception("MEDCouplingAMRAttribute::buildCellFieldOnWithoutGhost : the mesh specified is not in the progeny of this !");
+  //
+  MEDCouplingAutoRefCountObjectPtr<MEDCouplingIMesh> im(mesh->getImageMesh()->buildWithGhost(_ghost_lev));
+  std::vector<int> cgs(mesh->getImageMesh()->getCellGridStructure()),cgsWG(im->getCellGridStructure());
+  MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> arr2(DataArrayDouble::New());
+  arr2->alloc(mesh->getImageMesh()->getNumberOfCells(),arr->getNumberOfComponents());
+  std::vector< std::pair<int,int> > cgs2(MEDCouplingStructuredMesh::GetCompactFrmtFromDimensions(cgs));
+  MEDCouplingStructuredMesh::ApplyGhostOnCompactFrmt(cgs2,_ghost_lev);
+  std::vector<int> fakeFactors(mesh->getImageMesh()->getSpaceDimension(),1);
+  MEDCouplingIMesh::SpreadCoarseToFine(arr,cgsWG,arr2,cgs2,fakeFactors);
+  arr2->copyStringInfoFrom(*arr);
+  //
+  MEDCouplingAutoRefCountObjectPtr<MEDCouplingFieldDouble> ret(MEDCouplingFieldDouble::New(ON_CELLS));
+  ret->setMesh(mesh->getImageMesh());
+  ret->setArray(arr2);
+  ret->setName(arr->getName());
+  return ret.retn();
+}
+
 /*!
  * This method synchronizes from fine to coarse direction arrays. This method makes the hypothesis that \a this has been allocated before using
  * MEDCouplingAMRAttribute::alloc method.
+ * This method \b DOES \b NOT \b UPDATE the ghost zones (neither the fine not the coarse)
+ *
+ * \sa synchronizeFineToCoarseBetween
  */
 void MEDCouplingAMRAttribute::synchronizeFineToCoarse()
 {
@@ -650,14 +847,37 @@ void MEDCouplingAMRAttribute::synchronizeFineToCoarse()
   while(sz>1)
     {
       sz--;
-      const MEDCouplingGridCollection *fine(_levs[sz]),*coarse(_levs[sz-1]);
-      MEDCouplingGridCollection::SynchronizeFineToCoarse(_ghost_lev,fine,coarse);
+      synchronizeFineToCoarseByOneLevel((int)sz);
     }
 }
 
+/*!
+ * This method allows to synchronizes fields on fine patches on level \a fromLev to coarser patches at \a toLev level.
+ * This method operates step by step performing the synchronization the \a fromLev to \a fromLev - 1, then \a fromLev -1 to \a fromLev - 2 ...
+ * until reaching \a toLev level.
+ * This method \b DOES \b NOT \b UPDATE the ghost zones (neither the fine not the coarse).
+ *
+ * \param [in] fromLev - an existing level considered as fine so bigger than \a toLev
+ * \param [in] toLev - an existing level considered as the target level to reach.
+ *
+ */
+void MEDCouplingAMRAttribute::synchronizeFineToCoarseBetween(int fromLev, int toLev)
+{
+  int nbl(getNumberOfLevels());
+  if(fromLev<0 || toLev<0 || fromLev>=nbl || toLev>=nbl)
+    throw INTERP_KERNEL::Exception("MEDCouplingAMRAttribute::synchronizeFineToCoarseBetween : fromLev and toLev must be >= 0 and lower than number of levels in this !");
+  if(fromLev==toLev)
+    return ;//nothing to do
+  if(fromLev<toLev)
+    throw INTERP_KERNEL::Exception("MEDCouplingAMRAttribute::synchronizeFineToCoarseBetween : the fromLev level is lower than toLev level ! Call synchronizeFineToCoarseBetween ");
+  for(int i=fromLev;i>toLev;i--)
+    synchronizeFineToCoarseByOneLevel(i);
+}
+
 /*!
  * This method synchronizes from coarse to fine arrays and fine to fine each other (if _ghost_lev is >0). This method makes the hypothesis that \a this has been allocated before using
  * MEDCouplingAMRAttribute::alloc method.
+ * This method \b DOES \b UPDATE \b the \b ghost \b zone (contrary to synchronizeFineToCoarse method)
  */
 void MEDCouplingAMRAttribute::synchronizeCoarseToFine()
 {
@@ -665,11 +885,30 @@ void MEDCouplingAMRAttribute::synchronizeCoarseToFine()
     throw INTERP_KERNEL::Exception("MEDCouplingAMRAttribute::synchronizeCoarseToFine : not any levels in this !");
   std::size_t sz(_levs.size());
   //
-  for(std::size_t i=1;i<sz;i++)
-    {
-      const MEDCouplingGridCollection *fine(_levs[i]),*coarse(_levs[i-1]);
-      MEDCouplingGridCollection::SynchronizeCoarseToFine(_ghost_lev,coarse,fine);
-    }
+  for(std::size_t i=0;i<sz-1;i++)
+    synchronizeCoarseToFineByOneLevel((int)i);
+}
+
+/*!
+ * This method allows to synchronizes fields on coarse patches on level \a fromLev to their respective refined patches at \a toLev level.
+ * This method operates step by step performing the synchronization the \a fromLev to \a fromLev + 1, then \a fromLev + 1 to \a fromLev + 2 ...
+ * until reaching \a toLev level.
+ * This method \b DOES \b UPDATE \b the \b ghost \b zone (contrary to synchronizeFineToCoarseBetween method)
+ *
+ * \param [in] fromLev - an existing level considered as coarse so lower than \a toLev
+ * \param [in] toLev - an existing level considered as the target level to reach.
+ */
+void MEDCouplingAMRAttribute::synchronizeCoarseToFineBetween(int fromLev, int toLev)
+{
+  int nbl(getNumberOfLevels());
+  if(fromLev<0 || toLev<0 || fromLev>=nbl || toLev>=nbl)
+    throw INTERP_KERNEL::Exception("MEDCouplingAMRAttribute::synchronizeCoarseToFineBetween : fromLev and toLev must be >= 0 and lower than number of levels in this !");
+  if(fromLev==toLev)
+    return ;//nothing to do
+  if(fromLev>toLev)
+    throw INTERP_KERNEL::Exception("MEDCouplingAMRAttribute::synchronizeCoarseToFineBetween : the fromLev level is greater than toLev level ! Call synchronizeFineToCoarseBetween instead !");
+  for(int i=fromLev;i<toLev;i++)
+    synchronizeCoarseToFineByOneLevel(i);
 }
 
 /*!
@@ -686,22 +925,22 @@ void MEDCouplingAMRAttribute::synchronizeCoarseToFine()
  */
 void MEDCouplingAMRAttribute::synchronizeAllGhostZones()
 {
-  if(_levs.empty())
+  int sz(getNumberOfLevels());
+  if(sz==0)
     throw INTERP_KERNEL::Exception("MEDCouplingAMRAttribute::synchronizeFineEachOther : not any levels in this !");
   // 1st - synchronize from coarse to the finest all the patches (excepted the god father one)
-  std::size_t sz(_levs.size());
-  for(std::size_t i=1;i<sz;i++)
+  for(int i=1;i<sz;i++)
     {
       const MEDCouplingGridCollection *fine(_levs[i]),*coarse(_levs[i-1]);
       MEDCouplingGridCollection::SynchronizeCoarseToFineOnlyInGhostZone(_ghost_lev,coarse,fine);
     }
   // 2nd - classical direct sublevel inside common patch
-  for(std::size_t i=1;i<sz;i++)
+  for(int i=1;i<sz;i++)
     {
-      const MEDCouplingGridCollection *fine(_levs[i]);
-      if(!fine)
+      const MEDCouplingGridCollection *curLev(_levs[i]);
+      if(!curLev)
         throw INTERP_KERNEL::Exception("MEDCouplingAMRAttribute::synchronizeFineEachOtherInGhostZone : presence of a NULL element !");
-      fine->synchronizeFineEachOther(_ghost_lev,_neighbors[i]);
+      curLev->synchronizeFineEachOther(_ghost_lev,_neighbors[i]);
     }
   // 3rd - mixed level
   for(std::vector< std::pair<const MEDCouplingCartesianAMRPatch *,const MEDCouplingCartesianAMRPatch *> >::const_iterator it=_mixed_lev_neighbors.begin();it!=_mixed_lev_neighbors.end();it++)
@@ -710,13 +949,36 @@ void MEDCouplingAMRAttribute::synchronizeAllGhostZones()
       DataArrayDoubleCollection::SynchronizeGhostZoneOfOneUsingTwo(_ghost_lev,(*it).first,firstDAC,(*it).second,secondDAC);
     }
   // 4th - same level but with far ancestor.
-  for(std::size_t i=1;i<sz;i++)
+  for(int i=1;i<sz;i++)
     {
       const MEDCouplingGridCollection *fine(_levs[i]);
       fine->synchronizeFineEachOtherExt(_ghost_lev,_cross_lev_neighbors[i]);
     }
 }
 
+/*!
+ * This method synchronizes all direct children of \a mesh each other.
+ */
+void MEDCouplingAMRAttribute::synchronizeAllGhostZonesOfDirectChidrenOf(const MEDCouplingCartesianAMRMeshGen *mesh)
+{
+  if(!mesh)
+    throw INTERP_KERNEL::Exception("MEDCouplingAMRAttribute::synchronizeAllGhostZonesOfDirectChidrenOf : input mesh is NULL !");
+  int level(mesh->getAbsoluteLevelRelativeTo(_gf)),sz(getNumberOfLevels());
+  if(level<0 || level>=sz-1)
+    throw INTERP_KERNEL::Exception("MEDCouplingAMRAttribute::synchronizeAllGhostZonesOfDirectChidrenOf : the specified level does not exist ! Must be in [0,nbOfLevelsOfThis-1) !");
+  const std::vector< std::pair<const MEDCouplingCartesianAMRPatch *,const MEDCouplingCartesianAMRPatch *> >& itemsToFilter(_neighbors[level+1]);
+  std::vector< std::pair<const MEDCouplingCartesianAMRPatch *,const MEDCouplingCartesianAMRPatch *> > itemsToSync; itemsToSync.reserve(itemsToFilter.size());
+  for(std::vector< std::pair<const MEDCouplingCartesianAMRPatch *,const MEDCouplingCartesianAMRPatch *> >::const_iterator it=itemsToFilter.begin();it!=itemsToFilter.end();it++)
+    {
+      if((*it).first->getMesh()->getFather()==mesh && (*it).second->getMesh()->getFather()==mesh)
+        itemsToSync.push_back(std::pair<const MEDCouplingCartesianAMRPatch *,const MEDCouplingCartesianAMRPatch *>((*it).first,(*it).second));
+    }
+  const MEDCouplingGridCollection *curLev(_levs[level+1]);
+  if(!curLev)
+    throw INTERP_KERNEL::Exception("MEDCouplingAMRAttribute::synchronizeAllGhostZonesOfDirectChidrenOf : presence of a NULL element !");
+  curLev->synchronizeFineEachOther(_ghost_lev,itemsToSync);
+}
+
 /*!
  * This method allocates all DataArrayDouble instances stored recursively in \a this.
  *
@@ -829,6 +1091,58 @@ MEDCouplingAMRAttribute::MEDCouplingAMRAttribute(MEDCouplingCartesianAMRMesh *gf
     }
 }
 
+MEDCouplingAMRAttribute::MEDCouplingAMRAttribute(const MEDCouplingAMRAttribute& other, bool deepCpyGF):MEDCouplingDataForGodFather(other,deepCpyGF),_ghost_lev(other._ghost_lev),_levs(other._levs.size()),_neighbors(other._neighbors),_mixed_lev_neighbors(other._mixed_lev_neighbors),_cross_lev_neighbors(other._cross_lev_neighbors)
+{
+  std::size_t sz(other._levs.size());
+  for(std::size_t i=0;i<sz;i++)
+    {
+      const MEDCouplingGridCollection *elt(other._levs[i]);
+      if(elt)
+        {
+          _levs[i]=other._levs[i]->deepCpy(_gf,other._gf);
+        }
+    }
+  //_cross_lev_neighbors(other._cross_lev_neighbors)
+  sz=other._neighbors.size();
+  for(std::size_t i=0;i<sz;i++)
+    {
+      const std::vector< std::pair<const MEDCouplingCartesianAMRPatch *,const MEDCouplingCartesianAMRPatch *> >& neigh2(other._neighbors[i]);
+      std::size_t sz2(neigh2.size());
+      std::vector< std::pair<const MEDCouplingCartesianAMRPatch *,const MEDCouplingCartesianAMRPatch *> >& neigh3(_neighbors[i]);
+      for(std::size_t j=0;j<sz2;j++)
+        {
+          const MEDCouplingCartesianAMRPatch *p1(neigh2[j].first),*p2(neigh2[j].second);
+          std::vector<int> pp1(p1->getMesh()->getPositionRelativeTo(other._gf)),pp2(p2->getMesh()->getPositionRelativeTo(other._gf));
+          neigh3[j].first=_gf->getPatchAtPosition(pp1);
+          neigh3[j].second=_gf->getPatchAtPosition(pp2);
+        }
+    }
+  //
+  sz=other._mixed_lev_neighbors.size();
+  for(std::size_t i=0;i<sz;i++)
+    {
+      const MEDCouplingCartesianAMRPatch *p1(other._mixed_lev_neighbors[i].first),*p2(other._mixed_lev_neighbors[i].second);
+      std::vector<int> pp1(p1->getMesh()->getPositionRelativeTo(other._gf)),pp2(p2->getMesh()->getPositionRelativeTo(other._gf));
+      _mixed_lev_neighbors[i].first=_gf->getPatchAtPosition(pp1);
+      _mixed_lev_neighbors[i].second=_gf->getPatchAtPosition(pp2);
+    }
+  //
+  sz=other._cross_lev_neighbors.size();
+  for(std::size_t i=0;i<sz;i++)
+    {
+      const std::vector< std::pair<const MEDCouplingCartesianAMRPatch *,const MEDCouplingCartesianAMRPatch *> >& neigh2(other._cross_lev_neighbors[i]);
+      std::size_t sz2(neigh2.size());
+      std::vector< std::pair<const MEDCouplingCartesianAMRPatch *,const MEDCouplingCartesianAMRPatch *> >& neigh3(_cross_lev_neighbors[i]);
+      for(std::size_t j=0;j<sz2;j++)
+        {
+          const MEDCouplingCartesianAMRPatch *p1(neigh2[j].first),*p2(neigh2[j].second);
+          std::vector<int> pp1(p1->getMesh()->getPositionRelativeTo(other._gf)),pp2(p2->getMesh()->getPositionRelativeTo(other._gf));
+          neigh3[j].first=_gf->getPatchAtPosition(pp1);
+          neigh3[j].second=_gf->getPatchAtPosition(pp2);
+        }
+    }
+}
+
 const DataArrayDoubleCollection& MEDCouplingAMRAttribute::findCollectionAttachedTo(const MEDCouplingCartesianAMRMeshGen *m) const
 {
   for(std::vector< MEDCouplingAutoRefCountObjectPtr<MEDCouplingGridCollection> >::const_iterator it=_levs.begin();it!=_levs.end();it++)
@@ -845,3 +1159,21 @@ const DataArrayDoubleCollection& MEDCouplingAMRAttribute::findCollectionAttached
     }
   throw INTERP_KERNEL::Exception("MEDCouplingAMRAttribute::findCollectionAttachedTo : unable to find such part of mesh in this !");
 }
+
+void MEDCouplingAMRAttribute::synchronizeFineToCoarseByOneLevel(int level)
+{
+  int nbl(getNumberOfLevels());
+  if(level<=0 || level>=nbl)
+    throw INTERP_KERNEL::Exception("MEDCouplingAMRAttribute::synchronizeFineToCoarseByOneLevel : the input level must be in ]0,nb_of_levels[ !");
+  const MEDCouplingGridCollection *fine(_levs[level]),*coarse(_levs[level-1]);
+  MEDCouplingGridCollection::SynchronizeFineToCoarse(_ghost_lev,fine,coarse);
+}
+
+void MEDCouplingAMRAttribute::synchronizeCoarseToFineByOneLevel(int level)
+{
+  int nbl(getNumberOfLevels());
+  if(level<0 || level>=nbl-1)
+    throw INTERP_KERNEL::Exception("MEDCouplingAMRAttribute::synchronizeFineToCoarseByOneLevel : the input level must be in [0,nb_of_levels[ !");
+  const MEDCouplingGridCollection *fine(_levs[level+1]),*coarse(_levs[level]);
+  MEDCouplingGridCollection::SynchronizeCoarseToFine(_ghost_lev,coarse,fine);
+}