Salome HOME
OverlapDEC: bug fix. Bounding box adjustment was negative.
[modules/med.git] / src / MEDCoupling / MEDCouplingAMRAttribute.cxx
index b9c1559dee304b9c7a093c58ff17ea489989673a..f49b7bf9d7e456622bb9d08625be607a14acb25f 100644 (file)
@@ -1,4 +1,4 @@
-// Copyright (C) 2007-2014  CEA/DEN, EDF R&D
+// Copyright (C) 2007-2015  CEA/DEN, EDF R&D
 //
 // This library is free software; you can redistribute it and/or
 // modify it under the terms of the GNU Lesser General Public
 #include "MEDCouplingIMesh.hxx"
 
 #include <sstream>
+#include <fstream>
 
 using namespace ParaMEDMEM;
 
+/// @cond INTERNAL
 DataArrayDoubleCollection *DataArrayDoubleCollection::New(const std::vector< std::pair<std::string,int> >& fieldNames)
 {
   return new DataArrayDoubleCollection(fieldNames);
@@ -51,6 +53,21 @@ void DataArrayDoubleCollection::dellocTuples()
     _arrs[i].first->reAlloc(0);
 }
 
+void DataArrayDoubleCollection::copyFrom(const DataArrayDoubleCollection& other)
+{
+  std::size_t sz(_arrs.size());
+  if(sz!=other._arrs.size())
+    throw INTERP_KERNEL::Exception("DataArrayDoubleCollection::copyFrom : size are not the same !");
+  for(std::size_t i=0;i<sz;i++)
+    {
+      DataArrayDouble *thisArr(_arrs[i].first);
+      const DataArrayDouble *otherArr(other._arrs[i].first);
+      if(!thisArr || !otherArr)
+        throw INTERP_KERNEL::Exception("DataArrayDoubleCollection::copyFrom : empty DataArray !");
+      thisArr->cpyFrom(*otherArr);
+    }
+}
+
 void DataArrayDoubleCollection::spillInfoOnComponents(const std::vector< std::vector<std::string> >& compNames)
 {
   std::size_t sz(_arrs.size());
@@ -75,6 +92,29 @@ void DataArrayDoubleCollection::spillNatures(const std::vector<NatureOfField>& n
     }
 }
 
+std::vector< std::pair < std::string, std::vector<std::string> > > DataArrayDoubleCollection::getInfoOnComponents() const
+{
+  std::size_t sz(_arrs.size());
+  std::vector< std::pair < std::string, std::vector<std::string> > > ret(sz);
+  for(std::size_t i=0;i<sz;i++)
+    {
+      const DataArrayDouble *elt(_arrs[i].first);
+      if(!elt)
+        throw INTERP_KERNEL::Exception("DataArrayDoubleCollection::getInfoOnComponents : empty array !");
+      ret[i]=std::pair < std::string, std::vector<std::string> >(elt->getName(),elt->getInfoOnComponents());
+    }
+  return ret;
+}
+
+std::vector<NatureOfField> DataArrayDoubleCollection::getNatures() const
+{
+  std::size_t sz(_arrs.size());
+  std::vector<NatureOfField> ret(sz);
+  for(std::size_t i=0;i<sz;i++)
+    ret[i]=_arrs[i].second;
+  return ret;
+}
+
 std::vector<DataArrayDouble *> DataArrayDoubleCollection::retrieveFields() const
 {
   std::size_t sz(_arrs.size());
@@ -108,6 +148,44 @@ const DataArrayDouble *DataArrayDoubleCollection::getFieldWithName(const std::st
   throw INTERP_KERNEL::Exception(oss.str().c_str());
 }
 
+DataArrayDouble *DataArrayDoubleCollection::getFieldWithName(const std::string& name)
+{
+  std::vector<std::string> vec;
+  for(std::vector< std::pair< MEDCouplingAutoRefCountObjectPtr<DataArrayDouble>, NatureOfField > >::iterator it=_arrs.begin();it!=_arrs.end();it++)
+    {
+      DataArrayDouble *obj((*it).first);
+      if(obj)
+        {
+          if(obj->getName()==name)
+            return obj;
+          else
+            vec.push_back(obj->getName());
+        }
+    }
+  std::ostringstream oss; oss << "DataArrayDoubleCollection::getFieldWithName non const : fieldName \"" << name << "\" does not exist in this ! Possibilities are :";
+  std::copy(vec.begin(),vec.end(),std::ostream_iterator<std::string>(oss," "));
+  throw INTERP_KERNEL::Exception(oss.str().c_str());
+}
+
+DataArrayDouble *DataArrayDoubleCollection::at(int pos)
+{
+  if(pos<0 || pos>=(int)_arrs.size())
+    throw INTERP_KERNEL::Exception("DataArrayDoubleCollection::at (non const) : pos must be in [0,nbOfFields) !");
+  return _arrs[pos].first;
+}
+
+const DataArrayDouble *DataArrayDoubleCollection::at(int pos) const
+{
+  if(pos<0 || pos>=(int)_arrs.size())
+    throw INTERP_KERNEL::Exception("DataArrayDoubleCollection::at : pos must be in [0,nbOfFields) !");
+  return _arrs[pos].first;
+}
+
+int DataArrayDoubleCollection::size() const
+{
+  return (int)_arrs.size();
+}
+
 void DataArrayDoubleCollection::SynchronizeFineToCoarse(int ghostLev, const MEDCouplingCartesianAMRMeshGen *fatherOfFineMesh, int patchId, const DataArrayDoubleCollection *fine, DataArrayDoubleCollection *coarse)
 {
   if(!fine || !coarse)
@@ -174,7 +252,9 @@ void DataArrayDoubleCollection::SynchronizeGhostZoneOfOneUsingTwo(int ghostLev,
   for(std::size_t i=0;i<sz;i++)
     {
       const DataArrayDouble *zeArrWhichGhostsWillBeUpdated(p1dac->_arrs[i].first);
-      MEDCouplingCartesianAMRPatch::UpdateNeighborsOfOneWithTwoMixedLev(ghostLev,p1,p2,const_cast<DataArrayDouble *>(zeArrWhichGhostsWillBeUpdated),p2dac->_arrs[i].first);
+      DataArrayDoubleCollection::CheckSameNatures(p1dac->_arrs[i].second,p2dac->_arrs[i].second);
+      bool isConservative(DataArrayDoubleCollection::IsConservativeNature(p1dac->_arrs[i].second));
+      MEDCouplingCartesianAMRPatch::UpdateNeighborsOfOneWithTwoMixedLev(ghostLev,p1,p2,const_cast<DataArrayDouble *>(zeArrWhichGhostsWillBeUpdated),p2dac->_arrs[i].first,isConservative);
     }
 }
 
@@ -216,6 +296,12 @@ 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]);
+      if(info.second<=0)
+        {
+          std::ostringstream oss; oss << "DataArrayDoubleCollection constructor : At pos #" << i << " the array with name \"" << info.first << "\" as a number of components equal to " << info.second;
+          oss << " It has to be >=1 !";
+          throw INTERP_KERNEL::Exception(oss.str().c_str());
+        }
       _arrs[i].first=DataArrayDouble::New();
       _arrs[i].first->alloc(0,info.second);
       _arrs[i].first->setName(info.first);
@@ -244,15 +330,11 @@ std::size_t DataArrayDoubleCollection::getHeapMemorySizeWithoutChildren() const
   return ret;
 }
 
-std::vector<const BigMemoryObject *> DataArrayDoubleCollection::getDirectChildren() const
+std::vector<const BigMemoryObject *> DataArrayDoubleCollection::getDirectChildrenWithNull() const
 {
   std::vector<const BigMemoryObject *> ret;
   for(std::vector< std::pair< MEDCouplingAutoRefCountObjectPtr<DataArrayDouble>, NatureOfField > >::const_iterator it=_arrs.begin();it!=_arrs.end();it++)
-    {
-      const DataArrayDouble *pt((*it).first);
-      if(pt)
-        ret.push_back(pt);
-    }
+    ret.push_back((const DataArrayDouble *)(*it).first);
   return ret;
 }
 
@@ -340,6 +422,26 @@ void MEDCouplingGridCollection::spillNatures(const std::vector<NatureOfField>& n
     (*it).second->spillNatures(nfs);
 }
 
+std::vector< std::pair<std::string, std::vector<std::string> > > MEDCouplingGridCollection::getInfoOnComponents() const
+{
+  if(_map_of_dadc.empty())
+    throw INTERP_KERNEL::Exception("MEDCouplingGridCollection::getInfoOnComponents : empty map !");
+  const DataArrayDoubleCollection *elt(_map_of_dadc[0].second);
+  if(!elt)
+    throw INTERP_KERNEL::Exception("MEDCouplingGridCollection::getInfoOnComponents : null pointer !");
+  return elt->getInfoOnComponents();
+}
+
+std::vector<NatureOfField> MEDCouplingGridCollection::getNatures() const
+{
+  if(_map_of_dadc.empty())
+    throw INTERP_KERNEL::Exception("MEDCouplingGridCollection::getNatures : empty map !");
+  const DataArrayDoubleCollection *elt(_map_of_dadc[0].second);
+  if(!elt)
+    throw INTERP_KERNEL::Exception("MEDCouplingGridCollection::getNatures : null pointer !");
+  return elt->getNatures();
+}
+
 bool MEDCouplingGridCollection::presenceOf(const MEDCouplingCartesianAMRMeshGen *m, int& pos) const
 {
   int ret(0);
@@ -361,6 +463,52 @@ const DataArrayDoubleCollection& MEDCouplingGridCollection::getFieldsAt(int pos)
   return *_map_of_dadc[pos].second;
 }
 
+DataArrayDoubleCollection& MEDCouplingGridCollection::getFieldsAt(int pos)
+{
+  if(pos<0 || pos>(int)_map_of_dadc.size())
+    throw INTERP_KERNEL::Exception("MEDCouplingGridCollection::getFieldsAt (non const) : invalid pos given in input ! Must be in [0,size) !");
+  return *_map_of_dadc[pos].second;
+}
+
+/*!
+ * This method copies for all grids intersecting themselves (between \a this and \a other), the values of fields of \a other to the intersecting
+ * part of fields of \a this. The fields are expected to be the same between \a other and \a this.
+ * This methods makes the hypothesis that \a this and \a other share two god father that are compatible each other that is to say with the same cell grid structure.
+ */
+void MEDCouplingGridCollection::copyOverlappedZoneFrom(int ghostLev, const MEDCouplingGridCollection& other)
+{
+  for(std::vector< std::pair<const MEDCouplingCartesianAMRMeshGen *,MEDCouplingAutoRefCountObjectPtr<DataArrayDoubleCollection> > >::iterator it=_map_of_dadc.begin();it!=_map_of_dadc.end();it++)
+    {
+      std::vector<int> deltaThis,deltaOther;
+      std::vector< std::pair<int,int> > rgThis((*it).first->positionRelativeToGodFather(deltaThis));
+      std::vector<int> thisSt((*it).first->getImageMesh()->getCellGridStructure());
+      std::transform(thisSt.begin(),thisSt.end(),thisSt.begin(),std::bind2nd(std::plus<int>(),2*ghostLev));
+      for(std::vector< std::pair<const MEDCouplingCartesianAMRMeshGen *,MEDCouplingAutoRefCountObjectPtr<DataArrayDoubleCollection> > >::const_iterator it2=other._map_of_dadc.begin();it2!=other._map_of_dadc.end();it2++)
+        {
+          std::vector< std::pair<int,int> > rgOther((*it2).first->positionRelativeToGodFather(deltaOther));
+          if(MEDCouplingStructuredMesh::AreRangesIntersect(rgThis,rgOther))
+            {
+              std::vector< std::pair<int,int> > isect(MEDCouplingStructuredMesh::IntersectRanges(rgThis,rgOther));
+              std::vector< std::pair<int,int> > pThis,pOther;
+              MEDCouplingStructuredMesh::ChangeReferenceFromGlobalOfCompactFrmt(rgThis,isect,pThis,true);
+              MEDCouplingStructuredMesh::ChangeReferenceFromGlobalOfCompactFrmt(rgOther,isect,pOther,true);
+              std::vector<int> otherSt((*it2).first->getImageMesh()->getCellGridStructure());
+              MEDCouplingStructuredMesh::ApplyGhostOnCompactFrmt(pThis,ghostLev);
+              MEDCouplingStructuredMesh::ApplyGhostOnCompactFrmt(pOther,ghostLev);
+              std::transform(otherSt.begin(),otherSt.end(),otherSt.begin(),std::bind2nd(std::plus<int>(),2*ghostLev));
+              int sz((*it2).second->size());
+              for(int i=0;i<sz;i++)
+                {
+                  const DataArrayDouble *otherArr((*it2).second->at(i));
+                  DataArrayDouble *thisArr((*it).second->at(i));
+                  MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> partOfOther(MEDCouplingStructuredMesh::ExtractFieldOfDoubleFrom(otherSt,otherArr,pOther));
+                  MEDCouplingStructuredMesh::AssignPartOfFieldOfDoubleUsing(thisSt,thisArr,pThis,partOfOther);
+                }
+            }
+        }
+    }
+}
+
 void MEDCouplingGridCollection::SynchronizeFineToCoarse(int ghostLev, const MEDCouplingGridCollection *fine, const MEDCouplingGridCollection *coarse)
 {
   if(!fine || !coarse)
@@ -559,15 +707,11 @@ std::size_t MEDCouplingGridCollection::getHeapMemorySizeWithoutChildren() const
   return ret;
 }
 
-std::vector<const BigMemoryObject *> MEDCouplingGridCollection::getDirectChildren() const
+std::vector<const BigMemoryObject *> MEDCouplingGridCollection::getDirectChildrenWithNull() const
 {
   std::vector<const BigMemoryObject *> ret;
   for(std::vector< std::pair<const MEDCouplingCartesianAMRMeshGen *,MEDCouplingAutoRefCountObjectPtr<DataArrayDoubleCollection> > >::const_iterator it=_map_of_dadc.begin();it!=_map_of_dadc.end();it++)
-    {
-      const DataArrayDoubleCollection *col((*it).second);
-      if(col)
-        ret.push_back(col);
-    }
+    ret.push_back((const DataArrayDoubleCollection *)(*it).second);
   return ret;
 }
 
@@ -584,12 +728,19 @@ void MEDCouplingGridCollection::updateTime() const
     }
 }
 
-MEDCouplingCartesianAMRMeshGen *MEDCouplingDataForGodFather::getMyGodFather()
+/// @endcond
+
+MEDCouplingCartesianAMRMesh *MEDCouplingDataForGodFather::getMyGodFather()
+{
+  return _gf;
+}
+
+const MEDCouplingCartesianAMRMesh *MEDCouplingDataForGodFather::getMyGodFather() const
 {
   return _gf;
 }
 
-MEDCouplingDataForGodFather::MEDCouplingDataForGodFather(MEDCouplingCartesianAMRMeshGen *gf):_gf(gf),_tlc(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 !");
@@ -601,7 +752,7 @@ void MEDCouplingDataForGodFather::checkGodFatherFrozen() const
   _tlc.checkConst();
 }
 
-bool MEDCouplingDataForGodFather::changeGodFather(MEDCouplingCartesianAMRMeshGen *gf)
+bool MEDCouplingDataForGodFather::changeGodFather(MEDCouplingCartesianAMRMesh *gf)
 {
   bool ret(_tlc.keepTrackOfNewTL(gf));
   if(ret)
@@ -618,9 +769,9 @@ MEDCouplingDataForGodFather::MEDCouplingDataForGodFather(const MEDCouplingDataFo
   other._tlc.checkConst();
   if(deepCpyGF)
     {
-      const MEDCouplingCartesianAMRMeshGen *gf(other._gf);
+      const MEDCouplingCartesianAMRMesh *gf(other._gf);
       if(gf)
-        _gf=gf->deepCpy();
+        _gf=gf->deepCpy(0);
       _tlc.keepTrackOfNewTL(_gf);
     }
 }
@@ -628,12 +779,12 @@ MEDCouplingDataForGodFather::MEDCouplingDataForGodFather(const MEDCouplingDataFo
 /*!
  * This method creates, attach to a main AMR mesh \a gf ( called god father :-) ) and returns a data linked to \a gf ready for the computation.
  */
-MEDCouplingAMRAttribute *MEDCouplingAMRAttribute::New(MEDCouplingCartesianAMRMeshGen *gf, const std::vector< std::pair<std::string,int> >& fieldNames, int ghostLev)
+MEDCouplingAMRAttribute *MEDCouplingAMRAttribute::New(MEDCouplingCartesianAMRMesh *gf, const std::vector< std::pair<std::string,int> >& fieldNames, int ghostLev)
 {
   return new MEDCouplingAMRAttribute(gf,fieldNames,ghostLev);
 }
 
-MEDCouplingAMRAttribute *MEDCouplingAMRAttribute::New(MEDCouplingCartesianAMRMeshGen *gf, const std::vector< std::pair<std::string, std::vector<std::string> > >& fieldNames, int ghostLev)
+MEDCouplingAMRAttribute *MEDCouplingAMRAttribute::New(MEDCouplingCartesianAMRMesh *gf, const std::vector< std::pair<std::string, std::vector<std::string> > >& fieldNames, int ghostLev)
 {
   std::size_t sz(fieldNames.size());
   std::vector< std::pair<std::string,int> > fieldNames2(sz);
@@ -728,7 +879,21 @@ const DataArrayDouble *MEDCouplingAMRAttribute::getFieldOn(MEDCouplingCartesianA
           return ddc.getFieldWithName(fieldName);
         }
     }
-  throw INTERP_KERNEL::Exception("MEDCouplingAMRAttribute::retrieveFieldOn : the mesh specified is not in the progeny of this !");
+  throw INTERP_KERNEL::Exception("MEDCouplingAMRAttribute::getFieldOn : the mesh specified is not in the progeny of this !");
+}
+
+DataArrayDouble *MEDCouplingAMRAttribute::getFieldOn(MEDCouplingCartesianAMRMeshGen *mesh, const std::string& fieldName)
+{
+  for(std::vector< MEDCouplingAutoRefCountObjectPtr<MEDCouplingGridCollection> >::iterator it=_levs.begin();it!=_levs.end();it++)
+    {
+      int tmp(-1);
+      if((*it)->presenceOf(mesh,tmp))
+        {
+          DataArrayDoubleCollection& ddc((*it)->getFieldsAt(tmp));
+          return ddc.getFieldWithName(fieldName);
+        }
+    }
+  throw INTERP_KERNEL::Exception("MEDCouplingAMRAttribute::getFieldOn non const : the mesh specified is not in the progeny of this !");
 }
 
 /*!
@@ -800,7 +965,6 @@ MEDCouplingFieldDouble *MEDCouplingAMRAttribute::buildCellFieldOnWithGhost(MEDCo
  */
 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++)
     {
@@ -831,9 +995,169 @@ MEDCouplingFieldDouble *MEDCouplingAMRAttribute::buildCellFieldOnWithoutGhost(ME
   return ret.retn();
 }
 
+
+std::string MEDCouplingAMRAttribute::writeVTHB(const std::string& fileName) const
+{
+  static const char EXT[]=".vthb";
+  std::string baseName,extName,zeFileName;
+  MEDCouplingMesh::SplitExtension(fileName,baseName,extName);
+  if(extName==EXT)
+    zeFileName=fileName;
+  else
+    { zeFileName=baseName; zeFileName+=EXT; }
+  //
+  std::ofstream ofs(fileName.c_str());
+  ofs << "<VTKFile type=\"vtkOverlappingAMR\" version=\"1.1\" byte_order=\"" << MEDCouplingByteOrderStr() << "\">\n";
+  const MEDCouplingCartesianAMRMesh *gf(getMyGodFather());
+  ofs << "  <vtkOverlappingAMR origin=\"";
+  const MEDCouplingIMesh *gfm(gf->getImageMesh());
+  std::vector<double> orig(gfm->getOrigin());
+  std::vector<double> spacing(gfm->getDXYZ());
+  int dim((int)orig.size());
+  std::copy(orig.begin(),orig.end(),std::ostream_iterator<double>(ofs," ")); ofs << "\" grid_description=\"";
+  for(int i=0;i<dim;i++)
+    {
+      char tmp[2]; tmp[0]='X'+i; tmp[1]='\0';
+      ofs << tmp;
+    }
+  ofs << "\">\n";
+  //
+  int maxLev(gf->getMaxNumberOfLevelsRelativeToThis()),kk(0);
+  for(int i=0;i<maxLev;i++)
+    {
+      std::vector<MEDCouplingCartesianAMRPatchGen *> patches(gf->retrieveGridsAt(i));
+      std::size_t sz(patches.size());
+      std::vector< MEDCouplingAutoRefCountObjectPtr<MEDCouplingCartesianAMRPatchGen> > patchesSafe(sz);
+      for(std::size_t j=0;j<sz;j++)
+        patchesSafe[j]=patches[j];
+      if(sz==0)
+        continue;
+      ofs << "    <Block level=\"" << i << "\" spacing=\"";
+      std::copy(spacing.begin(),spacing.end(),std::ostream_iterator<double>(ofs," "));
+      ofs << "\">\n";
+      if(i!=maxLev-1)
+        {
+          std::vector<int> factors(patches[0]->getMesh()->getFactors());
+          for(int k=0;k<dim;k++)
+            spacing[k]*=1./((double) factors[k]);
+        }
+      std::size_t jj(0);
+      for(std::vector<MEDCouplingCartesianAMRPatchGen *>::const_iterator it=patches.begin();it!=patches.end();it++,jj++,kk++)
+        {
+          ofs << "      <DataSet index=\"" << jj << "\" amr_box=\"";
+          const MEDCouplingCartesianAMRPatch *patchCast(dynamic_cast<const MEDCouplingCartesianAMRPatch *>(*it));
+          const MEDCouplingCartesianAMRMeshGen *mesh((*it)->getMesh());
+          if(patchCast)
+            {
+              const std::vector< std::pair<int,int> >& bltr(patchCast->getBLTRRangeRelativeToGF());
+              for(int pp=0;pp<dim;pp++)
+                ofs << bltr[pp].first << " " << bltr[pp].second-1 << " ";
+            }
+          else
+            {
+              const MEDCouplingIMesh *im((*it)->getMesh()->getImageMesh());
+              std::vector<int> cgs(im->getCellGridStructure());
+              for(int pp=0;pp<dim;pp++)
+                ofs << "0 " << cgs[pp]-1 << " ";
+            }
+          ofs << "\" file=\"";
+          //
+          int tmp(-1);
+          if(_levs[i]->presenceOf((*it)->getMesh(),tmp))
+            {
+              const DataArrayDoubleCollection& ddc(_levs[i]->getFieldsAt(tmp));
+              std::vector<DataArrayDouble *> arrs(ddc.retrieveFields());
+              std::size_t nbFields(arrs.size());
+              std::vector< MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> > arrsSafe(nbFields),arrs2Safe(nbFields);
+              std::vector< const MEDCouplingFieldDouble *> fields(nbFields);
+              std::vector< MEDCouplingAutoRefCountObjectPtr<MEDCouplingFieldDouble> > fieldsSafe(nbFields);
+              for(std::size_t pp=0;pp<nbFields;pp++)
+                arrsSafe[pp]=arrs[pp];
+              for(std::size_t pp=0;pp<nbFields;pp++)
+                {
+                  MEDCouplingAutoRefCountObjectPtr<MEDCouplingIMesh> im(mesh->getImageMesh()->buildWithGhost(_ghost_lev));
+                  std::vector<int> cgs(mesh->getImageMesh()->getCellGridStructure()),cgsWG(im->getCellGridStructure());
+                  arrs2Safe[pp]=DataArrayDouble::New();
+                  arrs2Safe[pp]->alloc(mesh->getImageMesh()->getNumberOfCells(),arrs[pp]->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(arrs[pp],cgsWG,arrs2Safe[pp],cgs2,fakeFactors);
+                  arrs2Safe[pp]->copyStringInfoFrom(*arrs[pp]);
+                  //
+                  fieldsSafe[pp]=MEDCouplingFieldDouble::New(ON_CELLS); fields[pp]=fieldsSafe[pp];
+                  fieldsSafe[pp]->setMesh(mesh->getImageMesh());
+                  fieldsSafe[pp]->setArray(arrs2Safe[pp]);
+                  fieldsSafe[pp]->setName(arrs[pp]->getName());
+                }
+              std::ostringstream vtiFileName; vtiFileName << baseName << "_" << kk << ".vti";
+              MEDCouplingFieldDouble::WriteVTK(vtiFileName.str(),fields,true);
+              //
+              ofs << vtiFileName.str() << "\">\n";
+              ofs << "      \n      </DataSet>\n";
+            }
+        }
+      ofs << "    </Block>\n";
+    }
+  //
+  ofs << "  </vtkOverlappingAMR>\n";
+  ofs << "</VTKFile>\n";
+  return zeFileName;
+}
+
+  /*!
+   * This method is useful just after a remesh after a time step computation to project values in \a this to the new
+   * mesh \a targetGF.
+   *
+   * This method performs a projection from \a this to a target AMR mesh \a targetGF.
+   * This method performs the projection by trying to transfer the finest information to \a targetGF.
+ * \b WARNING this method does not update the ghost zone, if any.
+ * The level0 of \a this god father must have the same structure than those of \a targetGF.
+ *
+ * This method makes checks that ghost size of \a this and \a targetGF are the same, and that
+ * the number of levels in \a this and in \a targetGF are also the same.
+ */
+MEDCouplingAMRAttribute *MEDCouplingAMRAttribute::projectTo(MEDCouplingCartesianAMRMesh *targetGF) const
+{
+  if(!targetGF)
+    throw INTERP_KERNEL::Exception("MEDCouplingAMRAttribute::projectTo : given other target god is NULL !");
+  if(_levs.empty())
+    throw INTERP_KERNEL::Exception("MEDCouplingAMRAttribute::projectTo : no levels in this !");
+  const MEDCouplingGridCollection *lev0(_levs[0]);
+  if(!lev0)
+    throw INTERP_KERNEL::Exception("MEDCouplingAMRAttribute::projectTo : lev0 is NULL !");
+  std::vector< std::pair < std::string, std::vector<std::string> > > fieldNames(lev0->getInfoOnComponents());
+  MEDCouplingAutoRefCountObjectPtr<MEDCouplingAMRAttribute> ret(MEDCouplingAMRAttribute::New(targetGF,fieldNames,_ghost_lev));
+  ret->spillNatures(lev0->getNatures());
+  ret->alloc();
+  int nbLevs(getNumberOfLevels());
+  if(targetGF->getMaxNumberOfLevelsRelativeToThis()!=nbLevs)
+    throw INTERP_KERNEL::Exception("MEDCouplingAMRAttribute::projectTo : number of levels of this and targetGF must be the same !");
+  // first step copy level0
+  if(getMyGodFather()->getImageMesh()->getCellGridStructure()!=targetGF->getImageMesh()->getCellGridStructure())
+    throw INTERP_KERNEL::Exception("MEDCouplingAMRAttribute::projectTo : god father of this and target ones do not have the same structure !");
+  const DataArrayDoubleCollection& col(lev0->getFieldsAt(0));
+  DataArrayDoubleCollection& colTarget(ret->_levs[0]->getFieldsAt(0));
+  colTarget.copyFrom(col);
+  // then go deeper and deeper
+  for(int i=1;i<nbLevs;i++)
+    {
+      ret->synchronizeCoarseToFineByOneLevel(i-1);
+      MEDCouplingGridCollection *targetCol(ret->_levs[i]);
+      if(!targetCol)
+        throw INTERP_KERNEL::Exception("MEDCouplingAMRAttribute::projectTo : null lev of target !");
+      const MEDCouplingGridCollection *thisCol(_levs[i]);
+      if(!thisCol)
+        throw INTERP_KERNEL::Exception("MEDCouplingAMRAttribute::projectTo : null lev of this !");
+      targetCol->copyOverlappedZoneFrom(_ghost_lev,*thisCol);
+    }
+  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
  */
@@ -854,6 +1178,7 @@ void MEDCouplingAMRAttribute::synchronizeFineToCoarse()
  * 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.
@@ -875,6 +1200,7 @@ void MEDCouplingAMRAttribute::synchronizeFineToCoarseBetween(int fromLev, int to
 /*!
  * 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()
 {
@@ -890,6 +1216,7 @@ void MEDCouplingAMRAttribute::synchronizeCoarseToFine()
  * 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.
@@ -933,10 +1260,10 @@ void MEDCouplingAMRAttribute::synchronizeAllGhostZones()
   // 2nd - classical direct sublevel inside common patch
   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++)
@@ -953,7 +1280,13 @@ void MEDCouplingAMRAttribute::synchronizeAllGhostZones()
 }
 
 /*!
- * This method
+ * This method works \b ONLY \b ON \b DIRECT \b SONS \b OF \a mesh. So only a part of patches at a given level is updated here.
+ * The ghost zone of all of these sons of \a mesh are updated using the brother patches (the patches sharing the \b SAME \a mesh).
+ * It is sometimes possible that a ghost zone of some sons of \a mesh are covered by a patch of same level but different father.
+ * For such cases, the ghost zones are \b NOT updated. If you need a more thorough (but more costly) ghost zone update use synchronizeAllGhostZonesAtASpecifiedLevel method instead.
+ *
+ * \param [in] mesh - an element in the progeny of god father in \a this, which the ghost zone of its sons will be updated each other.
+ *
  */
 void MEDCouplingAMRAttribute::synchronizeAllGhostZonesOfDirectChidrenOf(const MEDCouplingCartesianAMRMeshGen *mesh)
 {
@@ -962,15 +1295,53 @@ void MEDCouplingAMRAttribute::synchronizeAllGhostZonesOfDirectChidrenOf(const ME
   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 DataArrayDoubleCollection& colCoarse(findCollectionAttachedTo(mesh));
-  std::vector< const MEDCouplingCartesianAMRPatch *> directChildren(mesh->getPatches());
-  std::size_t nbOfDirChildren(directChildren.size());
-  for(std::size_t patchId=0;patchId<nbOfDirChildren;patchId++)
+  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++)
     {
-      const DataArrayDoubleCollection& colFine(findCollectionAttachedTo(directChildren[patchId]->getMesh()));
-      DataArrayDoubleCollection *colFine2(const_cast<DataArrayDoubleCollection *>(&colFine));
-      DataArrayDoubleCollection::SynchronizeCoarseToFineOnlyInGhostZone(_ghost_lev,mesh,(int)patchId,&colCoarse,colFine2);
+      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 updates \b all the patches at level \a level each other without consideration of their father.
+ * So this method is more time consuming than synchronizeAllGhostZonesOfDirectChidrenOf.
+ */
+void MEDCouplingAMRAttribute::synchronizeAllGhostZonesAtASpecifiedLevel(int level)
+{
+  int maxLev(getNumberOfLevels());
+  if(level<0 || level>=maxLev)
+    throw INTERP_KERNEL::Exception("MEDCouplingAMRAttribute::synchronizeAllGhostZonesAtASpecifiedLevel : the specified level must be in [0,maxLevel) !");
+  if(level==0)
+    return ;//at level 0 only one patch -> no need to update
+  // 1st step - updates all patches pairs at level \a level sharing the same father
+  const std::vector< std::pair<const MEDCouplingCartesianAMRPatch *,const MEDCouplingCartesianAMRPatch *> >& items(_neighbors[level]);
+  const MEDCouplingGridCollection *curLev(_levs[level]);
+  if(!curLev)
+    throw INTERP_KERNEL::Exception("MEDCouplingAMRAttribute::synchronizeAllGhostZonesAtASpecifiedLevel : presence of a NULL element !");
+  curLev->synchronizeFineEachOther(_ghost_lev,items);
+  //2nd step - updates all patches pairs at level \a level not sharing the same father
+  const std::vector< std::pair<const MEDCouplingCartesianAMRPatch *,const MEDCouplingCartesianAMRPatch *> >& items2(_cross_lev_neighbors[level]);
+  curLev->synchronizeFineEachOtherExt(_ghost_lev,items2);
+}
+
+/*!
+ * This method updates ghost zones of patches at level \a level whatever their father \b using \b father \b patches \b ONLY (at level \b level - 1).
+ * This method is useful to propagate to the ghost zone of childhood the modification.
+ */
+void MEDCouplingAMRAttribute::synchronizeAllGhostZonesAtASpecifiedLevelUsingOnlyFather(int level)
+{
+  int maxLev(getNumberOfLevels());
+  if(level<=0 || level>=maxLev)
+    throw INTERP_KERNEL::Exception("MEDCouplingAMRAttribute::synchronizeAllGhostZonesAtASpecifiedLevelUsingOnlyFather : the specified level must be in (0,maxLevel) !");
+  const MEDCouplingGridCollection *fine(_levs[level]),*coarse(_levs[level-1]);
+  MEDCouplingGridCollection::SynchronizeCoarseToFineOnlyInGhostZone(_ghost_lev,coarse,fine);
+  //_cross_lev_neighbors is not needed.
 }
 
 /*!
@@ -1008,7 +1379,7 @@ void MEDCouplingAMRAttribute::dealloc()
     }
 }
 
-bool MEDCouplingAMRAttribute::changeGodFather(MEDCouplingCartesianAMRMeshGen *gf)
+bool MEDCouplingAMRAttribute::changeGodFather(MEDCouplingCartesianAMRMesh *gf)
 {
   bool ret(MEDCouplingDataForGodFather::changeGodFather(gf));
   return ret;
@@ -1021,15 +1392,11 @@ std::size_t MEDCouplingAMRAttribute::getHeapMemorySizeWithoutChildren() const
   return ret;
 }
 
-std::vector<const BigMemoryObject *> MEDCouplingAMRAttribute::getDirectChildren() const
+std::vector<const BigMemoryObject *> MEDCouplingAMRAttribute::getDirectChildrenWithNull() const
 {
   std::vector<const BigMemoryObject *> ret;
   for(std::vector< MEDCouplingAutoRefCountObjectPtr<MEDCouplingGridCollection> >::const_iterator it=_levs.begin();it!=_levs.end();it++)
-    {
-      const MEDCouplingGridCollection *elt(*it);
-      if(elt)
-        ret.push_back(elt);
-    }
+    ret.push_back((const MEDCouplingGridCollection *)*it);
   return ret;
 }
 
@@ -1037,7 +1404,7 @@ void MEDCouplingAMRAttribute::updateTime() const
 {//tony
 }
 
-MEDCouplingAMRAttribute::MEDCouplingAMRAttribute(MEDCouplingCartesianAMRMeshGen *gf, const std::vector< std::pair<std::string,int> >& fieldNames, int ghostLev):MEDCouplingDataForGodFather(gf),_ghost_lev(ghostLev)
+MEDCouplingAMRAttribute::MEDCouplingAMRAttribute(MEDCouplingCartesianAMRMesh *gf, const std::vector< std::pair<std::string,int> >& fieldNames, int ghostLev):MEDCouplingDataForGodFather(gf),_ghost_lev(ghostLev)
 {
   //gf non empty, checked by constructor
   int maxLev(gf->getMaxNumberOfLevelsRelativeToThis());
@@ -1096,6 +1463,45 @@ MEDCouplingAMRAttribute::MEDCouplingAMRAttribute(const MEDCouplingAMRAttribute&
           _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