Salome HOME
MEDReader again
[modules/med.git] / src / MEDLoader / MEDFileMesh.cxx
index 9b0363e9e505eee9b97df4db122b050b559cea72..615abd7aaace8a0c9bd0483bbbe254288dcb0959 100644 (file)
@@ -20,6 +20,8 @@
 
 #include "MEDFileMesh.hxx"
 #include "MEDFileUtilities.hxx"
+#include "MEDFileFieldOverView.hxx"
+#include "MEDFileField.hxx"
 #include "MEDLoader.hxx"
 #include "MEDLoaderBase.hxx"
 
@@ -62,7 +64,7 @@ std::size_t MEDFileMesh::getHeapMemorySize() const
  *  \throw If there is no meshes in the file.
  *  \throw If the mesh in the file is of a not supported type.
  */
-MEDFileMesh *MEDFileMesh::New(const char *fileName) throw(INTERP_KERNEL::Exception)
+MEDFileMesh *MEDFileMesh::New(const char *fileName, MEDFileMeshReadSelector *mrs) throw(INTERP_KERNEL::Exception)
 {
   std::vector<std::string> ms=MEDLoader::GetMeshNames(fileName);
   if(ms.empty())
@@ -81,19 +83,19 @@ MEDFileMesh *MEDFileMesh::New(const char *fileName) throw(INTERP_KERNEL::Excepti
     case UNSTRUCTURED:
       {
         MEDCouplingAutoRefCountObjectPtr<MEDFileUMesh> ret=MEDFileUMesh::New();
-        ret->loadUMeshFromFile(fid,ms.front().c_str(),dt,it);
+        ret->loadUMeshFromFile(fid,ms.front().c_str(),dt,it,mrs);
         return (MEDFileUMesh *)ret.retn();
       }
     case CARTESIAN:
       {
         MEDCouplingAutoRefCountObjectPtr<MEDFileCMesh> ret=MEDFileCMesh::New();
-        ret->loadCMeshFromFile(fid,ms.front().c_str(),dt,it);
+        ret->loadCMeshFromFile(fid,ms.front().c_str(),dt,it,mrs);
         return (MEDFileCMesh *)ret.retn();
       }
     case CURVE_LINEAR:
       {
         MEDCouplingAutoRefCountObjectPtr<MEDFileCurveLinearMesh> ret=MEDFileCurveLinearMesh::New();
-        ret->loadCLMeshFromFile(fid,ms.front().c_str(),dt,it);
+        ret->loadCLMeshFromFile(fid,ms.front().c_str(),dt,it,mrs);
         return (MEDFileCurveLinearMesh *)ret.retn();
       }
     default:
@@ -118,7 +120,7 @@ MEDFileMesh *MEDFileMesh::New(const char *fileName) throw(INTERP_KERNEL::Excepti
  *  \throw If there is no mesh with given attributes in the file.
  *  \throw If the mesh in the file is of a not supported type.
  */
-MEDFileMesh *MEDFileMesh::New(const char *fileName, const char *mName, int dt, int it) throw(INTERP_KERNEL::Exception)
+MEDFileMesh *MEDFileMesh::New(const char *fileName, const char *mName, int dt, int it, MEDFileMeshReadSelector *mrs) throw(INTERP_KERNEL::Exception)
 {
   MEDFileUtilities::CheckFileForRead(fileName);
   ParaMEDMEM::MEDCouplingMeshType meshType;
@@ -131,19 +133,19 @@ MEDFileMesh *MEDFileMesh::New(const char *fileName, const char *mName, int dt, i
     case UNSTRUCTURED:
       {
         MEDCouplingAutoRefCountObjectPtr<MEDFileUMesh> ret=MEDFileUMesh::New();
-        ret->loadUMeshFromFile(fid,mName,dt,it);
+        ret->loadUMeshFromFile(fid,mName,dt,it,mrs);
         return (MEDFileUMesh *)ret.retn();
       }
     case CARTESIAN:
       {
         MEDCouplingAutoRefCountObjectPtr<MEDFileCMesh> ret=MEDFileCMesh::New();
-        ret->loadCMeshFromFile(fid,mName,dt,it);
+        ret->loadCMeshFromFile(fid,mName,dt,it,mrs);
         return (MEDFileCMesh *)ret.retn();
       }
     case CURVE_LINEAR:
       {
         MEDCouplingAutoRefCountObjectPtr<MEDFileCurveLinearMesh> ret=MEDFileCurveLinearMesh::New();
-        ret->loadCLMeshFromFile(fid,mName,dt,it);
+        ret->loadCLMeshFromFile(fid,mName,dt,it,mrs);
         return (MEDFileCurveLinearMesh *)ret.retn();
       }
     default:
@@ -485,6 +487,27 @@ void MEDFileMesh::assignFamilyNameWithGroupName() throw(INTERP_KERNEL::Exception
   _groups=groups;
 }
 
+/*!
+ * Removes all groups lying on no family. If there is no empty groups, \a this is let untouched.
+ * 
+ * \return the removed groups.
+ */
+std::vector<std::string> MEDFileMesh::removeEmptyGroups() throw(INTERP_KERNEL::Exception)
+{
+  std::vector<std::string> ret;
+  std::map<std::string, std::vector<std::string> > newGrps;
+  for(std::map<std::string, std::vector<std::string> >::const_iterator it=_groups.begin();it!=_groups.end();it++)
+    {
+      if((*it).second.empty())
+        ret.push_back((*it).first);
+      else
+        newGrps[(*it).first]=(*it).second;
+    }
+  if(!ret.empty())
+    _groups=newGrps;
+  return ret;
+}
+
 /*!
  * Removes a group from \a this mesh.
  *  \param [in] name - the name of the group to remove.
@@ -530,6 +553,62 @@ void MEDFileMesh::removeFamily(const char *name) throw(INTERP_KERNEL::Exception)
     }
 }
 
+/*!
+ * Removes all groups in \a this that are orphan. A group is orphan if this group lies on
+ * a set of families, themselves orphan. A family is said orphan if its id appears nowhere in
+ * family field whatever its level. This method also suppresses the orphan families.
+ * 
+ * \return - The list of removed groups names. 
+ *
+ * \sa MEDFileMesh::removeOrphanFamilies.
+ */
+std::vector<std::string> MEDFileMesh::removeOrphanGroups() throw(INTERP_KERNEL::Exception)
+{
+  removeOrphanFamilies();
+  return removeEmptyGroups();
+}
+
+/*!
+ * Removes all families in \a this that are orphan. A family is said orphan if its id appears nowhere in
+ * family field whatever its level. Groups are updated in consequence, that is to say all groups lying on orphan family, will see their families list modified.
+ * 
+ * \return - The list of removed families names.
+ * \sa MEDFileMesh::removeOrphanGroups.
+ */
+std::vector<std::string> MEDFileMesh::removeOrphanFamilies() throw(INTERP_KERNEL::Exception)
+{
+  MEDCouplingAutoRefCountObjectPtr<DataArrayInt> allFamIdsInUse=computeAllFamilyIdsInUse();
+  std::vector<std::string> ret;
+  if(!((DataArrayInt*)allFamIdsInUse))
+    {
+      ret=getFamiliesNames();
+      _families.clear(); _groups.clear();
+      return ret;
+    }
+  std::map<std::string,int> famMap;
+  std::map<std::string, std::vector<std::string> > grps(_groups);
+  for(std::map<std::string,int>::const_iterator it=_families.begin();it!=_families.end();it++)
+    {
+      if(allFamIdsInUse->presenceOfValue((*it).second))
+        famMap[(*it).first]=(*it).second;
+      else
+        {
+          ret.push_back((*it).first);
+          std::vector<std::string> grpsOnEraseFam=getGroupsOnFamily((*it).first.c_str());
+          for(std::vector<std::string>::const_iterator it2=grpsOnEraseFam.begin();it2!=grpsOnEraseFam.end();it2++)
+            {
+              std::map<std::string, std::vector<std::string> >::iterator it3=grps.find(*it2);//it3!=grps.empty() thanks to copy
+              std::vector<std::string>& famv=(*it3).second;
+              std::vector<std::string>::iterator it4=std::find(famv.begin(),famv.end(),(*it).first);//it4!=famv.end() thanks to copy
+              famv.erase(it4);
+            }
+        }
+    }
+  if(!ret.empty())
+    { _families=famMap; _groups=grps; }
+  return ret;
+}
+
 /*!
  * Renames a group in \a this mesh.
  *  \param [in] oldName - a current name of the group to rename.
@@ -549,8 +628,8 @@ void MEDFileMesh::changeGroupName(const char *oldName, const char *newName) thro
       throw INTERP_KERNEL::Exception(oss.str().c_str());
     }
   std::string nname(newName);
-  it=_groups.find(nname);
-  if(it!=_groups.end())
+  std::map<std::string, std::vector<std::string> >::iterator it2=_groups.find(nname);
+  if(it2!=_groups.end())
     {
       std::ostringstream oss; oss << "Such groupname \"" << newName << "\" already exists ! Kill it before !";
       throw INTERP_KERNEL::Exception(oss.str().c_str());
@@ -1065,6 +1144,23 @@ std::vector<int> MEDFileMesh::getFamiliesIds(const std::vector<std::string>& fam
   return ret;
 }
 
+/*!
+ * Returns a maximal abs(id) of families in \a this mesh.
+ *  \return int - the maximal norm of family id.
+ *  \throw If there are no families in \a this mesh.
+ */
+int MEDFileMesh::getMaxAbsFamilyId() const throw(INTERP_KERNEL::Exception)
+{
+  if(_families.empty())
+    throw INTERP_KERNEL::Exception("MEDFileMesh::getMaxFamilyId : no families set !");
+  int ret=-std::numeric_limits<int>::max();
+  for(std::map<std::string,int>::const_iterator it=_families.begin();it!=_families.end();it++)
+    {
+      ret=std::max(std::abs((*it).second),ret);
+    }
+  return ret;
+}
+
 /*!
  * Returns a maximal id of families in \a this mesh.
  *  \return int - the maximal family id.
@@ -1073,7 +1169,7 @@ std::vector<int> MEDFileMesh::getFamiliesIds(const std::vector<std::string>& fam
 int MEDFileMesh::getMaxFamilyId() const throw(INTERP_KERNEL::Exception)
 {
   if(_families.empty())
-    throw INTERP_KERNEL::Exception("MEDFileUMesh::getMaxFamilyId : no families set !");
+    throw INTERP_KERNEL::Exception("MEDFileMesh::getMaxFamilyId : no families set !");
   int ret=-std::numeric_limits<int>::max();
   for(std::map<std::string,int>::const_iterator it=_families.begin();it!=_families.end();it++)
     {
@@ -1090,7 +1186,7 @@ int MEDFileMesh::getMaxFamilyId() const throw(INTERP_KERNEL::Exception)
 int MEDFileMesh::getMinFamilyId() const throw(INTERP_KERNEL::Exception)
 {
   if(_families.empty())
-    throw INTERP_KERNEL::Exception("MEDFileUMesh::getMinFamilyId : no families set !");
+    throw INTERP_KERNEL::Exception("MEDFileMesh::getMinFamilyId : no families set !");
   int ret=std::numeric_limits<int>::max();
   for(std::map<std::string,int>::const_iterator it=_families.begin();it!=_families.end();it++)
     {
@@ -1099,6 +1195,20 @@ int MEDFileMesh::getMinFamilyId() const throw(INTERP_KERNEL::Exception)
   return ret;
 }
 
+/*!
+ * Returns a maximal id of families in \a this mesh. Not only named families are
+ * considered but all family fields as well.
+ *  \return int - the maximal family id.
+ */
+int MEDFileMesh::getTheMaxAbsFamilyId() const throw(INTERP_KERNEL::Exception)
+{
+  int m1=-std::numeric_limits<int>::max();
+  for(std::map<std::string,int>::const_iterator it=_families.begin();it!=_families.end();it++)
+    m1=std::max(std::abs((*it).second),m1);
+  int m2=getMaxAbsFamilyIdInArrays();
+  return std::max(m1,m2);
+}
+
 /*!
  * Returns a maximal id of families in \a this mesh. Not only named families are
  * considered but all family fields as well.
@@ -1113,6 +1223,11 @@ int MEDFileMesh::getTheMaxFamilyId() const throw(INTERP_KERNEL::Exception)
   return std::max(m1,m2);
 }
 
+/*!
+ * Returns a minimal id of families in \a this mesh. Not only named families are
+ * considered but all family fields as well.
+ *  \return int - the minimal family id.
+ */
 int MEDFileMesh::getTheMinFamilyId() const throw(INTERP_KERNEL::Exception)
 {
   int m1=std::numeric_limits<int>::max();
@@ -1122,6 +1237,11 @@ int MEDFileMesh::getTheMinFamilyId() const throw(INTERP_KERNEL::Exception)
   return std::min(m1,m2);
 }
 
+/*!
+ * This method only considers the maps. The contain of family array is ignored here.
+ * 
+ * \sa MEDFileMesh::computeAllFamilyIdsInUse
+ */
 DataArrayInt *MEDFileMesh::getAllFamiliesIdsReferenced() const throw(INTERP_KERNEL::Exception)
 {
   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret=DataArrayInt::New();
@@ -1133,6 +1253,27 @@ DataArrayInt *MEDFileMesh::getAllFamiliesIdsReferenced() const throw(INTERP_KERN
   return ret.retn();
 }
 
+/*!
+ * This method does not consider map of family name, family id. Only family field array on different levels is considered.
+ * 
+ * \sa MEDFileMesh::getAllFamiliesIdsReferenced
+ */
+DataArrayInt *MEDFileMesh::computeAllFamilyIdsInUse() const throw(INTERP_KERNEL::Exception)
+{
+  std::vector<int> famLevs=getFamArrNonEmptyLevelsExt();
+  MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret;
+  for(std::vector<int>::const_iterator it=famLevs.begin();it!=famLevs.end();it++)
+    {
+      const DataArrayInt *arr=getFamilyFieldAtLevel(*it);//arr not null due to spec of getFamArrNonEmptyLevelsExt
+      MEDCouplingAutoRefCountObjectPtr<DataArrayInt> dv=arr->getDifferentValues();
+      if((DataArrayInt *) ret)
+        ret=dv->buildUnion(ret);
+      else
+        ret=dv;
+    }
+  return ret.retn();
+}
+
 /*!
  * true is returned if no modification has been needed. false if family
  * renumbering has been needed.       
@@ -1321,7 +1462,7 @@ void MEDFileMesh::normalizeFamIdsMEDFile() throw(INTERP_KERNEL::Exception)
   refId=-1;
   for(std::set<int>::const_reverse_iterator it2=levsS.rbegin();it2!=levsS.rend();it2++)
     {
-      const DataArrayInt *fam=getFamilyFieldAtLevel(1);
+      const DataArrayInt *fam=getFamilyFieldAtLevel(*it2);
       if(fam)
         {
           MEDCouplingAutoRefCountObjectPtr<DataArrayInt> tmp=fam->getDifferentValues();
@@ -1565,8 +1706,8 @@ void MEDFileMesh::setGroupsAtLevel(int meshDimRelToMaxExt, const std::vector<con
     }
   int offset=1;
   if(!_families.empty())
-    offset=getMaxFamilyId()+1;
-  TranslateFamilyIds(offset,fam,fidsOfGroups);
+    offset=getMaxAbsFamilyId()+1;
+  TranslateFamilyIds(meshDimRelToMaxExt==1?offset:-offset,fam,fidsOfGroups);
   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ids=fam->getDifferentValues();
   appendFamilyEntries(ids,fidsOfGroups,grpsName2);
   setFamilyFieldArr(meshDimRelToMaxExt,fam);
@@ -1599,9 +1740,13 @@ void MEDFileMesh::appendFamilyEntries(const DataArrayInt *famIds, const std::vec
 
 void MEDFileMesh::TranslateFamilyIds(int offset, DataArrayInt *famArr, std::vector< std::vector<int> >& famIdsPerGrp)
 {
-  famArr->applyLin(1,offset,0);
+  famArr->applyLin(offset>0?1:-1,offset,0);
   for(std::vector< std::vector<int> >::iterator it1=famIdsPerGrp.begin();it1!=famIdsPerGrp.end();it1++)
-    std::transform((*it1).begin(),(*it1).end(),(*it1).begin(),std::bind2nd(std::plus<int>(),offset));
+    {
+      if(offset<0)
+        std::transform((*it1).begin(),(*it1).end(),(*it1).begin(),std::negate<int>());
+      std::transform((*it1).begin(),(*it1).end(),(*it1).begin(),std::bind2nd(std::plus<int>(),offset));
+    }
 }
 
 /*!
@@ -1725,11 +1870,11 @@ void MEDFileMesh::getFamilyRepr(std::ostream& oss) const
  *  \throw If there is no mesh with given attributes in the file.
  *  \throw If the mesh in the file is not an unstructured one.
  */
-MEDFileUMesh *MEDFileUMesh::New(const char *fileName, const char *mName, int dt, int it) throw(INTERP_KERNEL::Exception)
+MEDFileUMesh *MEDFileUMesh::New(const char *fileName, const char *mName, int dt, int it, MEDFileMeshReadSelector *mrs) throw(INTERP_KERNEL::Exception)
 {
   MEDFileUtilities::CheckFileForRead(fileName);
   MEDFileUtilities::AutoFid fid=MEDfileOpen(fileName,MED_ACC_RDONLY);
-  return new MEDFileUMesh(fid,mName,dt,it);
+  return new MEDFileUMesh(fid,mName,dt,it,mrs);
 }
 
 /*!
@@ -1742,7 +1887,7 @@ MEDFileUMesh *MEDFileUMesh::New(const char *fileName, const char *mName, int dt,
  *  \throw If there is no meshes in the file.
  *  \throw If the mesh in the file is not an unstructured one.
  */
-MEDFileUMesh *MEDFileUMesh::New(const char *fileName) throw(INTERP_KERNEL::Exception)
+MEDFileUMesh *MEDFileUMesh::New(const char *fileName, MEDFileMeshReadSelector *mrs) throw(INTERP_KERNEL::Exception)
 {
   std::vector<std::string> ms=MEDLoader::GetMeshNames(fileName);
   if(ms.empty())
@@ -1756,7 +1901,7 @@ MEDFileUMesh *MEDFileUMesh::New(const char *fileName) throw(INTERP_KERNEL::Excep
   ParaMEDMEM::MEDCouplingMeshType meshType;
   std::string dummy2;
   MEDFileMeshL2::GetMeshIdFromName(fid,ms.front().c_str(),meshType,dt,it,dummy2);
-  return new MEDFileUMesh(fid,ms.front().c_str(),dt,it);
+  return new MEDFileUMesh(fid,ms.front().c_str(),dt,it,mrs);
 }
 
 /*!
@@ -1795,6 +1940,11 @@ MEDFileMesh *MEDFileUMesh::shallowCpy() const throw(INTERP_KERNEL::Exception)
   return ret.retn();
 }
 
+MEDFileMesh *MEDFileUMesh::createNewEmpty() const throw(INTERP_KERNEL::Exception)
+{
+  return new MEDFileUMesh;
+}
+
 MEDFileMesh *MEDFileUMesh::deepCpy() const throw(INTERP_KERNEL::Exception)
 {
   MEDCouplingAutoRefCountObjectPtr<MEDFileUMesh> ret=new MEDFileUMesh(*this);
@@ -1812,7 +1962,7 @@ MEDFileMesh *MEDFileUMesh::deepCpy() const throw(INTERP_KERNEL::Exception)
   for(std::vector< MEDCouplingAutoRefCountObjectPtr<MEDFileUMeshSplitL1> >::const_iterator it=_ms.begin();it!=_ms.end();it++,i++)
     {
       if((const MEDFileUMeshSplitL1 *)(*it))
-        ret->_ms[i]=(*it)->deepCpy();
+        ret->_ms[i]=(*it)->deepCpy(ret->_coords);
     }
   return ret.retn();
 }
@@ -1955,17 +2105,17 @@ MEDFileUMesh::MEDFileUMesh()
 {
 }
 
-MEDFileUMesh::MEDFileUMesh(med_idt fid, const char *mName, int dt, int it) throw(INTERP_KERNEL::Exception)
+MEDFileUMesh::MEDFileUMesh(med_idt fid, const char *mName, int dt, int it, MEDFileMeshReadSelector *mrs) throw(INTERP_KERNEL::Exception)
 try
   {
-    loadUMeshFromFile(fid,mName,dt,it);
+    loadUMeshFromFile(fid,mName,dt,it,mrs);
   }
 catch(INTERP_KERNEL::Exception& e)
   {
     throw e;
   }
 
-void MEDFileUMesh::loadUMeshFromFile(med_idt fid, const char *mName, int dt, int it) throw(INTERP_KERNEL::Exception)
+void MEDFileUMesh::loadUMeshFromFile(med_idt fid, const char *mName, int dt, int it, MEDFileMeshReadSelector *mrs) throw(INTERP_KERNEL::Exception)
 {
   MEDFileUMeshL2 loaderl2;
   ParaMEDMEM::MEDCouplingMeshType meshType;
@@ -1977,7 +2127,7 @@ void MEDFileUMesh::loadUMeshFromFile(med_idt fid, const char *mName, int dt, int
       std::ostringstream oss; oss << "Trying to load as unstructured an existing mesh with name '" << mName << "' !";
       throw INTERP_KERNEL::Exception(oss.str().c_str());
     }
-  loaderl2.loadAll(fid,mid,mName,dt,it);
+  loaderl2.loadAll(fid,mid,mName,dt,it,mrs);
   int lev=loaderl2.getNumberOfLevels();
   _ms.resize(lev);
   for(int i=0;i<lev;i++)
@@ -1987,7 +2137,7 @@ void MEDFileUMesh::loadUMeshFromFile(med_idt fid, const char *mName, int dt, int
       else
         _ms[i]=0;
     }
-  MEDFileMeshL2::ReadFamiliesAndGrps(fid,mName,_families,_groups);
+  MEDFileMeshL2::ReadFamiliesAndGrps(fid,mName,_families,_groups,mrs);
   //
   setName(loaderl2.getName());
   setDescription(loaderl2.getDescription());
@@ -1997,9 +2147,12 @@ void MEDFileUMesh::loadUMeshFromFile(med_idt fid, const char *mName, int dt, int
   setTimeValue(loaderl2.getTime());
   setTimeUnit(loaderl2.getTimeUnit());
   _coords=loaderl2.getCoords();
-  _fam_coords=loaderl2.getCoordsFamily();
-  _num_coords=loaderl2.getCoordsNum();
-  _name_coords=loaderl2.getCoordsName();
+  if(!mrs || mrs->isNodeFamilyFieldReading())
+    _fam_coords=loaderl2.getCoordsFamily();
+  if(!mrs || mrs->isNodeNumFieldReading())
+    _num_coords=loaderl2.getCoordsNum();
+  if(!mrs || mrs->isNodeNameFieldReading())
+    _name_coords=loaderl2.getCoordsName();
   computeRevNum();
 }
 
@@ -2067,6 +2220,57 @@ std::vector<int> MEDFileUMesh::getNonEmptyLevelsExt() const
   return ret0;
 }
 
+std::vector<int> MEDFileUMesh::getFamArrNonEmptyLevelsExt() const
+{
+  std::vector<int> ret;
+  const DataArrayInt *famCoo(_fam_coords);
+  if(famCoo)
+    ret.push_back(1);
+  int lev=0;
+  for(std::vector< MEDCouplingAutoRefCountObjectPtr<MEDFileUMeshSplitL1> >::const_iterator it=_ms.begin();it!=_ms.end();it++,lev--)
+    {
+      const MEDFileUMeshSplitL1 *cur(*it);
+      if(cur)
+        if(cur->getFamilyField())
+          ret.push_back(lev);
+    }
+  return ret;
+}
+
+std::vector<int> MEDFileUMesh::getNumArrNonEmptyLevelsExt() const
+{
+  std::vector<int> ret;
+  const DataArrayInt *numCoo(_num_coords);
+  if(numCoo)
+    ret.push_back(1);
+  int lev=0;
+  for(std::vector< MEDCouplingAutoRefCountObjectPtr<MEDFileUMeshSplitL1> >::const_iterator it=_ms.begin();it!=_ms.end();it++,lev--)
+    {
+      const MEDFileUMeshSplitL1 *cur(*it);
+      if(cur)
+        if(cur->getNumberField())
+          ret.push_back(lev);
+    }
+  return ret;
+}
+
+std::vector<int> MEDFileUMesh::getNameArrNonEmptyLevelsExt() const
+{
+  std::vector<int> ret;
+  const DataArrayAsciiChar *nameCoo(_name_coords);
+  if(nameCoo)
+    ret.push_back(1);
+  int lev=0;
+  for(std::vector< MEDCouplingAutoRefCountObjectPtr<MEDFileUMeshSplitL1> >::const_iterator it=_ms.begin();it!=_ms.end();it++,lev--)
+    {
+      const MEDFileUMeshSplitL1 *cur(*it);
+      if(cur)
+        if(cur->getNameField())
+          ret.push_back(lev);
+    }
+  return ret;
+}
+
 /*!
  * Returns all relative mesh levels (**excluding nodes**) where a given group is defined.
  * To include nodes, call getGrpNonEmptyLevelsExt() method.
@@ -2195,6 +2399,29 @@ std::vector<std::string> MEDFileUMesh::getGroupsOnSpecifiedLev(int meshDimRelToM
   return ret;
 }
 
+int MEDFileUMesh::getMaxAbsFamilyIdInArrays() const throw(INTERP_KERNEL::Exception)
+{
+  int ret=-std::numeric_limits<int>::max(),tmp=-1;
+  if((const DataArrayInt *)_fam_coords)
+    {
+      int val=_fam_coords->getMaxValue(tmp);
+      ret=std::max(ret,std::abs(val));
+    }
+  for(std::vector< MEDCouplingAutoRefCountObjectPtr<MEDFileUMeshSplitL1> >::const_iterator it=_ms.begin();it!=_ms.end();it++)
+    {
+      if((const MEDFileUMeshSplitL1 *)(*it))
+        {
+          const DataArrayInt *da=(*it)->getFamilyField();
+          if(da)
+            {
+              int val=da->getMaxValue(tmp);
+              ret=std::max(ret,std::abs(val));
+            }
+        }
+    }
+  return ret;
+}
+
 int MEDFileUMesh::getMaxFamilyIdInArrays() const throw(INTERP_KERNEL::Exception)
 {
   int ret=-std::numeric_limits<int>::max(),tmp=-1;
@@ -2391,6 +2618,40 @@ int MEDFileUMesh::getNumberOfNodes() const throw(INTERP_KERNEL::Exception)
   return coo->getNumberOfTuples();
 }
 
+void MEDFileUMesh::whichAreNodesFetched(const MEDFileField1TSStructItem& st, const MEDFileFieldGlobsReal *globs, std::vector<bool>& nodesFetched) const throw(INTERP_KERNEL::Exception)
+{
+  std::size_t sz(st.getNumberOfItems());
+  int mdim(getMeshDimension());
+  for(std::size_t i=0;i<sz;i++)
+    {
+      INTERP_KERNEL::NormalizedCellType curGt(st[i].getGeo());
+      const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel(curGt);
+      int relDim((int)cm.getDimension()-mdim);
+      MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> um(getMeshAtLevel(relDim));
+      std::vector<int> d(um->getDistributionOfTypes());
+      std::size_t nbOfTypes(d.size()/3);
+      int offset=0,nbOfEltWT=-1;
+      for(std::size_t j=0;j<nbOfTypes;j++)
+        {
+          if(d[3*j]!=(int)curGt)
+            offset+=d[3*j+1];
+          else
+            { break; nbOfEltWT=d[3*j+1]; }
+        }
+      if(nbOfEltWT==-1)
+        throw INTERP_KERNEL::Exception("MEDFileUMesh::whichAreNodesFetched : asking for a geo type not present in this !");
+      um=dynamic_cast<MEDCouplingUMesh *>(um->buildPartOfMySelf2(offset,offset+nbOfEltWT,1,true));
+      if(st[i].getPflName().empty())
+        um->computeNodeIdsAlg(nodesFetched);
+      else
+        {
+          const DataArrayInt *arr(globs->getProfile(st[i].getPflName().c_str()));
+          um=dynamic_cast<MEDCouplingUMesh *>(um->buildPartOfMySelf(arr->begin(),arr->end(),true));
+          um->computeNodeIdsAlg(nodesFetched);
+        }
+    }
+}
+
 /*!
  * Returns the optional numbers of mesh entities of a given dimension transformed using
  * DataArrayInt::invertArrayN2O2O2N().
@@ -2444,9 +2705,7 @@ MEDCouplingUMesh *MEDFileUMesh::getGroup(int meshDimRelToMaxExt, const char *grp
   synchronizeTinyInfoOnLeaves();
   std::vector<std::string> tmp(1);
   tmp[0]=grp;
-  MEDCouplingUMesh *ret=getGroups(meshDimRelToMaxExt,tmp,renum);
-  ret->setName(grp);
-  return ret;
+  return getGroups(meshDimRelToMaxExt,tmp,renum);
 }
 
 /*!
@@ -2467,7 +2726,10 @@ MEDCouplingUMesh *MEDFileUMesh::getGroups(int meshDimRelToMaxExt, const std::vec
 {
   synchronizeTinyInfoOnLeaves();
   std::vector<std::string> fams2=getFamiliesOnGroups(grps);
-  return getFamilies(meshDimRelToMaxExt,fams2,renum);
+  MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> zeRet=getFamilies(meshDimRelToMaxExt,fams2,renum);
+  if(grps.size()==1 && ((MEDCouplingUMesh *)zeRet))
+    zeRet->setName(grps[0].c_str());
+  return zeRet.retn();
 }
 
 /*!
@@ -2489,9 +2751,7 @@ MEDCouplingUMesh *MEDFileUMesh::getFamily(int meshDimRelToMaxExt, const char *fa
   synchronizeTinyInfoOnLeaves();
   std::vector<std::string> tmp(1);
   tmp[0]=fam;
-  MEDCouplingUMesh *ret=getFamilies(meshDimRelToMaxExt,tmp,renum);
-  ret->setName(fam);
-  return ret;
+  return getFamilies(meshDimRelToMaxExt,tmp,renum);
 }
 
 /*!
@@ -2521,10 +2781,14 @@ MEDCouplingUMesh *MEDFileUMesh::getFamilies(int meshDimRelToMaxExt, const std::v
     }
   std::vector<int> famIds=getFamiliesIds(fams);
   const MEDFileUMeshSplitL1 *l1=getMeshAtLevSafe(meshDimRelToMaxExt);
+  MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> zeRet;
   if(!famIds.empty())
-    return l1->getFamilyPart(&famIds[0],&famIds[0]+famIds.size(),renum);
+    zeRet=l1->getFamilyPart(&famIds[0],&famIds[0]+famIds.size(),renum);
   else
-    return l1->getFamilyPart(0,0,renum);
+    zeRet=l1->getFamilyPart(0,0,renum);
+  if(fams.size()==1 && ((MEDCouplingUMesh *)zeRet))
+    zeRet->setName(fams[0].c_str());
+  return zeRet.retn();
 }
 
 /*!
@@ -2591,7 +2855,7 @@ MEDCouplingUMesh *MEDFileUMesh::getMeshAtLevel(int meshDimRelToMaxExt, bool renu
           MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> cc=_coords->deepCpy();
           umesh->setCoords(cc);
           MEDFileUMeshSplitL1::ClearNonDiscrAttributes(umesh);
-          umesh->setName(getName());
+          umesh->setName(getName().c_str());
           return umesh;
         }
     }
@@ -2670,6 +2934,29 @@ MEDCouplingUMesh *MEDFileUMesh::getLevelM3Mesh(bool renum) const throw(INTERP_KE
   return getMeshAtLevel(-3,renum);
 }
 
+/*!
+ * This method returns a vector of mesh parts containing each exactly one geometric type.
+ * This method will never launch an automatic computation of split by type (an INTERP_KERNEL::Exception will be then thrown).
+ * This method is only for memory aware users.
+ */
+std::vector<MEDCoupling1GTUMesh *> MEDFileUMesh::getDirectUndergroundSingleGeoTypeMeshes(int meshDimRelToMax) const throw(INTERP_KERNEL::Exception)
+{
+  const MEDFileUMeshSplitL1 *sp(getMeshAtLevSafe(meshDimRelToMax));
+  return sp->getDirectUndergroundSingleGeoTypeMeshes();
+}
+
+/*!
+ * This method returns the part of \a this having the geometric type \a gt.
+ * If such part is not existing an exception will be thrown.
+ */
+MEDCoupling1GTUMesh *MEDFileUMesh::getDirectUndergroundSingleGeoTypeMesh(INTERP_KERNEL::NormalizedCellType gt) const throw(INTERP_KERNEL::Exception)
+{
+  const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel(gt);
+  int lev=(int)cm.getDimension()-getMeshDimension();
+  const MEDFileUMeshSplitL1 *sp(getMeshAtLevSafe(lev));
+  return sp->getDirectUndergroundSingleGeoTypeMesh(gt);
+}
+
 const MEDFileUMeshSplitL1 *MEDFileUMesh::getMeshAtLevSafe(int meshDimRelToMaxExt) const throw(INTERP_KERNEL::Exception)
 {
   if(meshDimRelToMaxExt==1)
@@ -2719,7 +3006,6 @@ void MEDFileUMesh::checkMeshDimCoherency(int meshDim, int meshDimRelToMax) const
  *  \param [in] coords - the new node coordinates array.
  *  \throw If \a coords == \c NULL.
  */
-
 void MEDFileUMesh::setCoords(DataArrayDouble *coords) throw(INTERP_KERNEL::Exception)
 {
   if(!coords)
@@ -2731,6 +3017,9 @@ void MEDFileUMesh::setCoords(DataArrayDouble *coords) throw(INTERP_KERNEL::Excep
   _fam_coords=DataArrayInt::New();
   _fam_coords->alloc(nbOfTuples,1);
   _fam_coords->fillWithZero();
+  for(std::vector< MEDCouplingAutoRefCountObjectPtr<MEDFileUMeshSplitL1> >::iterator it=_ms.begin();it!=_ms.end();it++)
+    if((MEDFileUMeshSplitL1 *)(*it))
+      (*it)->setCoords(coords);
 }
 
 /*!
@@ -2836,7 +3125,7 @@ void MEDFileUMesh::duplicateNodesOnM1Group(const char *grpNameM1, DataArrayInt *
   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> szOfCellGrpOfSameType(tmp00);
   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> idInMsOfCellGrpOfSameType(tmp11);
   //
-  newm1->setName(getName());
+  newm1->setName(getName().c_str());
   const DataArrayInt *fam=getFamilyFieldAtLevel(-1);
   if(!fam)
     throw INTERP_KERNEL::Exception("MEDFileUMesh::duplicateNodesOnM1Group : internal problem !");
@@ -3027,9 +3316,19 @@ void MEDFileUMesh::addNodeGroup(const DataArrayInt *ids) throw(INTERP_KERNEL::Ex
   if(!((DataArrayInt *)_fam_coords))
     { _fam_coords=DataArrayInt::New(); _fam_coords->alloc(nbOfNodes,1); _fam_coords->fillWithZero(); }
   //
-  addGroupUnderground(ids,_fam_coords);
+  addGroupUnderground(true,ids,_fam_coords);
 }
 
+/*!
+ * Adds a group of nodes/cells/faces/edges to \a this mesh.
+ *  \param [in] ids - a DataArrayInt providing ids and a name of the group to add.
+ *          The ids should be sorted and different each other (MED file norm).
+ *  \throw If the node coordinates array is not set.
+ *  \throw If \a ids == \c NULL.
+ *  \throw If \a ids->getName() == "".
+ *  \throw If \a ids does not respect the MED file norm.
+ *  \throw If a group with name \a ids->getName() already exists.
+ */
 void MEDFileUMesh::addGroup(int meshDimRelToMaxExt, const DataArrayInt *ids) throw(INTERP_KERNEL::Exception)
 {
   std::vector<int> levs=getNonEmptyLevelsExt();
@@ -3042,14 +3341,14 @@ void MEDFileUMesh::addGroup(int meshDimRelToMaxExt, const DataArrayInt *ids) thr
     { addNodeGroup(ids); return ; }
   MEDFileUMeshSplitL1 *lev=getMeshAtLevSafe(meshDimRelToMaxExt);
   DataArrayInt *fam=lev->getOrCreateAndGetFamilyField();
-  addGroupUnderground(ids,fam);
+  addGroupUnderground(false,ids,fam);
 }
 
 /*!
  * \param [in] ids ids and group name of the new group to add. The ids should be sorted and different each other (MED file norm).
  * \parma [in,out] famArr family array on level of interest to be renumbered. The input pointer should be not \c NULL (no check of that will be performed)
  */
-void MEDFileUMesh::addGroupUnderground(const DataArrayInt *ids, DataArrayInt *famArr) throw(INTERP_KERNEL::Exception)
+void MEDFileUMesh::addGroupUnderground(bool isNodeGroup, const DataArrayInt *ids, DataArrayInt *famArr) throw(INTERP_KERNEL::Exception)
 {
   if(!ids)
     throw INTERP_KERNEL::Exception("MEDFileUMesh::addGroup : NULL pointer in input !");
@@ -3070,7 +3369,7 @@ void MEDFileUMesh::addGroupUnderground(const DataArrayInt *ids, DataArrayInt *fa
   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> diffFamIds=famIds->getDifferentValues();
   std::vector<int> familyIds;
   std::vector< MEDCouplingAutoRefCountObjectPtr<DataArrayInt> > idsPerfamiliyIds;
-  int maxVal=getTheMaxFamilyId()+1;
+  int maxVal=getTheMaxAbsFamilyId()+1;
   std::map<std::string,int> families(_families);
   std::map<std::string, std::vector<std::string> > groups(_groups);
   std::vector<std::string> fams;
@@ -3090,7 +3389,8 @@ void MEDFileUMesh::addGroupUnderground(const DataArrayInt *ids, DataArrayInt *fa
             { familyIds.push_back(*famId); idsPerfamiliyIds.push_back(ret0); fams.push_back(FindOrCreateAndGiveFamilyWithId(families,*famId,created)); } // adding *famId in grp
           else
             {
-              familyIds.push_back(maxVal); idsPerfamiliyIds.push_back(ids2); std::string locFamName=FindOrCreateAndGiveFamilyWithId(families,maxVal,created);
+              familyIds.push_back(isNodeGroup?maxVal:-maxVal); idsPerfamiliyIds.push_back(ids2);
+              std::string locFamName=FindOrCreateAndGiveFamilyWithId(families,isNodeGroup?maxVal:-maxVal,created);
               fams.push_back(locFamName);
               if(existsFamily(*famId))
                 {
@@ -3102,12 +3402,12 @@ void MEDFileUMesh::addGroupUnderground(const DataArrayInt *ids, DataArrayInt *fa
         }
       else
         {
-          familyIds.push_back(maxVal); idsPerfamiliyIds.push_back(ret0); // modifying all other groups on *famId to lie on maxVal and on maxVal+1
-          familyIds.push_back(maxVal+1); idsPerfamiliyIds.push_back(ids2);//grp lie only on maxVal+1
-          std::string n2(FindOrCreateAndGiveFamilyWithId(families,maxVal+1,created)); fams.push_back(n2);
+          familyIds.push_back(isNodeGroup?maxVal:-maxVal); idsPerfamiliyIds.push_back(ret0); // modifying all other groups on *famId to lie on maxVal and on maxVal+1
+          familyIds.push_back(isNodeGroup?maxVal+1:-maxVal-1); idsPerfamiliyIds.push_back(ids2);//grp lie only on maxVal+1
+          std::string n2(FindOrCreateAndGiveFamilyWithId(families,isNodeGroup?maxVal+1:-maxVal-1,created)); fams.push_back(n2);
           if(existsFamily(*famId))
             {
-              std::string n1(FindOrCreateAndGiveFamilyWithId(families,maxVal,created)); std::vector<std::string> v(2); v[0]=n1; v[1]=n2;
+              std::string n1(FindOrCreateAndGiveFamilyWithId(families,isNodeGroup?maxVal:-maxVal,created)); std::vector<std::string> v(2); v[0]=n1; v[1]=n2;
               ChangeAllGroupsContainingFamily(groups,getFamilyNameGivenId(*famId).c_str(),v);
             }
           maxVal+=2;
@@ -3189,6 +3489,49 @@ void MEDFileUMesh::setMeshAtLevel(int meshDimRelToMax, MEDCouplingUMesh *m, bool
     _ms[-meshDimRelToMax]=new MEDFileUMeshSplitL1(m,newOrOld);
 }
 
+/*!
+ * This method allows to set at once the content of different levels in \a this.
+ * This method is equivalent to a series of call to MEDFileUMesh::setMeshAtLevel.
+ *
+ * \param [in] ms - List of unstructured meshes lying on the same coordinates and having different mesh dimesnion.
+ * \param [in] renum - the parameter (set to false by default) that tells the beheviour if there is a mesh on \a ms that is not geo type sorted.
+ *                     If false, an exception ois thrown. If true the mesh is reordered automatically. It is highly recommanded to let this parameter to false.
+ *
+ * \throw If \a there is a null pointer in \a ms.
+ * \sa MEDFileUMesh::setMeshAtLevel
+ */
+void MEDFileUMesh::setMeshes(const std::vector<const MEDCouplingUMesh *>& ms, bool renum) throw(INTERP_KERNEL::Exception)
+{
+  if(ms.empty())
+    return ;
+  const MEDCouplingUMesh *mRef=ms[0];
+  if(!mRef)
+    throw INTERP_KERNEL::Exception("MEDFileUMesh::setMeshes : null instance in the first element of input meshes !");
+  std::string name(mRef->getName());
+  const DataArrayDouble *coo(mRef->getCoords());
+  std::set<int> s;
+  int zeDim=-1;
+  for(std::vector<const MEDCouplingUMesh *>::const_iterator it=ms.begin();it!=ms.end();it++)
+    {
+      const MEDCouplingUMesh *cur(*it);
+      if(!cur)
+        throw INTERP_KERNEL::Exception("MEDFileUMesh::setMeshes : null instance in input vector of meshes !");
+      if(coo!=cur->getCoords())
+        throw INTERP_KERNEL::Exception("MEDFileUMesh::setMeshes : The input meshes do not share the same coordinates !");
+      int mdim=cur->getMeshDimension();
+      zeDim=std::max(zeDim,mdim);
+      if(s.find(mdim)!=s.end())
+        throw INTERP_KERNEL::Exception("MEDFileUMesh::setMeshes : The input meshes must share the same coordinates pointer, and should have different mesh dimension each other !");
+    }
+  for(std::vector<const MEDCouplingUMesh *>::const_iterator it=ms.begin();it!=ms.end();it++)
+    {
+      int mdim=(*it)->getMeshDimension();
+      setName((*it)->getName().c_str());
+      setMeshAtLevel(mdim-zeDim,const_cast<MEDCouplingUMesh *>(*it),renum);
+    }
+  setName(name.c_str());
+}
+
 /*!
  * Creates one MEDCouplingUMesh at a given level in \a this mesh from a sequence of
  * meshes each representing a group, and creates corresponding groups in \a this mesh.
@@ -3206,7 +3549,7 @@ void MEDFileUMesh::setMeshAtLevel(int meshDimRelToMax, MEDCouplingUMesh *m, bool
  *  \throw If names of some meshes in \a ms are equal.
  *  \throw If \a ms includes a mesh with an empty name.
  */
-void MEDFileUMesh::setGroupsFromScratch(int meshDimRelToMax, const std::vector<const MEDCouplingUMesh *>& ms) throw(INTERP_KERNEL::Exception)
+void MEDFileUMesh::setGroupsFromScratch(int meshDimRelToMax, const std::vector<const MEDCouplingUMesh *>& ms, bool renum) throw(INTERP_KERNEL::Exception)
 {
   if(ms.empty())
     throw INTERP_KERNEL::Exception("MEDFileUMesh::setGroupsFromScratch : expecting a non empty vector !");
@@ -3226,7 +3569,7 @@ void MEDFileUMesh::setGroupsFromScratch(int meshDimRelToMax, const std::vector<c
   std::vector<DataArrayInt *> corr;
   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> m=MEDCouplingUMesh::FuseUMeshesOnSameCoords(ms,_zipconn_pol,corr);
   std::vector< MEDCouplingAutoRefCountObjectPtr<DataArrayInt> > corr3(corr.begin(),corr.end());
-  setMeshAtLevel(meshDimRelToMax,m);
+  setMeshAtLevel(meshDimRelToMax,m,renum);
   std::vector<const DataArrayInt *> corr2(corr.begin(),corr.end());
   setGroupsAtLevel(meshDimRelToMax,corr2,true);
 }
@@ -3371,6 +3714,13 @@ void MEDFileUMesh::setRenumFieldArr(int meshDimRelToMaxExt, DataArrayInt *renumA
   return _ms[traducedRk]->setRenumArr(renumArr);
 }
 
+/*!
+ * Sets the optional names of mesh entities of a given dimension.
+ *  \param [in] meshDimRelToMaxExt - the relative dimension of mesh entities.
+ *  \param [in] nameArr - the array of the names.
+ *  \throw If there are no mesh entities of \a meshDimRelToMaxExt dimension in \a this mesh.
+ *  \throw If \a nameArr has an invalid size.
+ */
 void MEDFileUMesh::setNameFieldAtLevel(int meshDimRelToMaxExt, DataArrayAsciiChar *nameArr) throw(INTERP_KERNEL::Exception)
 {
   if(meshDimRelToMaxExt==1)
@@ -3382,14 +3732,14 @@ void MEDFileUMesh::setNameFieldAtLevel(int meshDimRelToMaxExt, DataArrayAsciiCha
         }
       DataArrayDouble *coo(_coords);
       if(!coo)
-        throw INTERP_KERNEL::Exception("MEDFileUMesh::setRenumFieldArr : the coordinates have not been set !");
-      nameArr->checkNbOfTuplesAndComp(coo->getNumberOfTuples(),MED_SNAME_SIZE,"MEDFileUMesh::setRenumArr : Problem in size of node numbering arr ! ");
+        throw INTERP_KERNEL::Exception("MEDFileUMesh::setNameFieldAtLevel : the coordinates have not been set !");
+      nameArr->checkNbOfTuplesAndComp(coo->getNumberOfTuples(),MED_SNAME_SIZE,"MEDFileUMesh::setNameFieldAtLevel : Problem in size of node numbering arr ! ");
       nameArr->incrRef();
       _name_coords=nameArr;
       return ;
     }
   if(meshDimRelToMaxExt>1)
-    throw INTERP_KERNEL::Exception("MEDFileUMesh::setRenumArr : Dimension request is invalid (>1) !");
+    throw INTERP_KERNEL::Exception("MEDFileUMesh::setNameFieldAtLevel : Dimension request is invalid (>1) !");
   int traducedRk=-meshDimRelToMaxExt;
   if(traducedRk>=(int)_ms.size())
     throw INTERP_KERNEL::Exception("Invalid mesh dim relative to max given ! To low !");
@@ -3470,6 +3820,22 @@ std::size_t MEDFileStructuredMesh::getHeapMemorySize() const
   return ret;
 }
 
+int MEDFileStructuredMesh::getMaxAbsFamilyIdInArrays() const throw(INTERP_KERNEL::Exception)
+{
+  int ret=-std::numeric_limits<int>::max(),tmp=-1;
+  if((const DataArrayInt *)_fam_nodes)
+    {
+      int val=_fam_nodes->getMaxValue(tmp);
+      ret=std::max(ret,std::abs(val));
+    }
+  if((const DataArrayInt *)_fam_cells)
+    {
+      int val=_fam_cells->getMaxValue(tmp);
+      ret=std::max(ret,std::abs(val));
+    }
+  return ret;
+}
+
 int MEDFileStructuredMesh::getMaxFamilyIdInArrays() const throw(INTERP_KERNEL::Exception)
 {
   int ret=-std::numeric_limits<int>::max(),tmp=-1;
@@ -3744,6 +4110,13 @@ void MEDFileStructuredMesh::setRenumFieldArr(int meshDimRelToMaxExt, DataArrayIn
     renumArr->incrRef();
 }
 
+/*!
+ * Sets the optional names of mesh entities of a given dimension.
+ *  \param [in] meshDimRelToMaxExt - the relative dimension of mesh entities.
+ *  \param [in] nameArr - the array of the names.
+ *  \throw If there are no mesh entities of \a meshDimRelToMaxExt dimension in \a this mesh.
+ *  \throw If \a nameArr has an invalid size.
+ */
 void MEDFileStructuredMesh::setNameFieldAtLevel(int meshDimRelToMaxExt, DataArrayAsciiChar *nameArr) throw(INTERP_KERNEL::Exception)
 {
   if(meshDimRelToMaxExt!=0 && meshDimRelToMaxExt!=1)
@@ -3871,6 +4244,46 @@ std::vector<int> MEDFileStructuredMesh::getNonEmptyLevelsExt() const
   return ret;
 }
 
+/*!
+ * Returns the set of extensive levels (nodes included) where not NULL family arr are defined.
+ */
+std::vector<int> MEDFileStructuredMesh::getFamArrNonEmptyLevelsExt() const
+{
+  std::vector<int> ret;
+  const DataArrayInt *famNodes(_fam_nodes),*famCells(_fam_cells);
+  if(famNodes)
+    ret.push_back(1);
+  if(famCells)
+    ret.push_back(0);
+  return ret;
+}
+
+/*!
+ * Returns the set of extensive levels (nodes included) where not NULL numbering arr are defined.
+ */
+std::vector<int> MEDFileStructuredMesh::getNumArrNonEmptyLevelsExt() const
+{
+  std::vector<int> ret;
+  const DataArrayInt *numNodes(_num_nodes),*numCells(_num_cells);
+  if(numNodes)
+    ret.push_back(1);
+  if(numCells)
+    ret.push_back(0);
+  return ret;
+}
+
+/*!
+ * Returns the set of extensive levels (nodes included) where not NULL naming arr are defined.
+ */
+std::vector<int> MEDFileStructuredMesh::getNameArrNonEmptyLevelsExt() const
+{
+  std::vector<int> ret;
+  const DataArrayAsciiChar *namesCells(_names_cells);
+  if(namesCells)
+    ret.push_back(0);
+  return ret;
+}
+
 /*!
  * no implementation here, it is not a bug, but intresically no polyhedra in \a this.
  */
@@ -3959,6 +4372,34 @@ int MEDFileStructuredMesh::getNumberOfNodes() const throw(INTERP_KERNEL::Excepti
   return cmesh->getNumberOfNodes();
 }
 
+void MEDFileStructuredMesh::whichAreNodesFetched(const MEDFileField1TSStructItem& st, const MEDFileFieldGlobsReal *globs, std::vector<bool>& nodesFetched) const throw(INTERP_KERNEL::Exception)
+{
+  if(st.getNumberOfItems()!=1)
+    throw INTERP_KERNEL::Exception("MEDFileStructuredMesh::whichAreNodesFetched : The sturture of field is not lying on single geo type ! it is not managed yet for structured mesh !");
+  if(st[0].getGeo()!=MEDCouplingStructuredMesh::GetGeoTypeGivenMeshDimension(getMeshDimension()))
+    throw INTERP_KERNEL::Exception("MEDFileStructuredMesh::whichAreNodesFetched : The sturture of field is not lying on expected geo type !");
+  if(getNumberOfNodes()!=(int)nodesFetched.size())
+    throw INTERP_KERNEL::Exception("MEDFileStructuredMesh::whichAreNodesFetched : invalid size of array !");
+  if(st[0].getPflName().empty())
+    {
+      std::fill(nodesFetched.begin(),nodesFetched.end(),true);
+      return ;
+    }
+  const DataArrayInt *arr(globs->getProfile(st[0].getPflName().c_str()));
+  const MEDCouplingStructuredMesh *cmesh=getStructuredMesh();//cmesh not null because getNumberOfNodes called before
+  int sz(nodesFetched.size());
+  for(const int *work=arr->begin();work!=arr->end();work++)
+    {
+      std::vector<int> conn;
+      cmesh->getNodeIdsOfCell(*work,conn);
+      for(std::vector<int>::const_iterator it=conn.begin();it!=conn.end();it++)
+        if(*it>=0 && *it<sz)
+          nodesFetched[*it]=true;
+        else
+          throw INTERP_KERNEL::Exception("MEDFileStructuredMesh::whichAreNodesFetched : internal error !");
+    }
+}
+
 med_geometry_type MEDFileStructuredMesh::GetGeoTypeFromMeshDim(int meshDim) throw(INTERP_KERNEL::Exception)
 {
   med_geometry_type geoTypeReq=MED_NONE;
@@ -3982,7 +4423,7 @@ med_geometry_type MEDFileStructuredMesh::GetGeoTypeFromMeshDim(int meshDim) thro
   return geoTypeReq;
 }
 
-void MEDFileStructuredMesh::loadStrMeshFromFile(MEDFileStrMeshL2 *strm, med_idt fid, const char *mName, int dt, int it) throw(INTERP_KERNEL::Exception)
+void MEDFileStructuredMesh::loadStrMeshFromFile(MEDFileStrMeshL2 *strm, med_idt fid, const char *mName, int dt, int it, MEDFileMeshReadSelector *mrs) throw(INTERP_KERNEL::Exception)
 {
   setName(strm->getName());
   setDescription(strm->getDescription());
@@ -3991,53 +4432,71 @@ void MEDFileStructuredMesh::loadStrMeshFromFile(MEDFileStrMeshL2 *strm, med_idt
   setOrder(strm->getOrder());
   setTimeValue(strm->getTime());
   setTimeUnit(strm->getTimeUnit());
-  MEDFileMeshL2::ReadFamiliesAndGrps(fid,mName,_families,_groups);
+  MEDFileMeshL2::ReadFamiliesAndGrps(fid,mName,_families,_groups,mrs);
   med_bool chgt=MED_FALSE,trsf=MED_FALSE;
   int nbOfElt=MEDmeshnEntity(fid,mName,dt,it,MED_NODE,MED_NONE,MED_FAMILY_NUMBER,MED_NODAL,&chgt,&trsf);
   if(nbOfElt>0)
     {
-      _fam_nodes=DataArrayInt::New();
-      _fam_nodes->alloc(nbOfElt,1);
-      MEDmeshEntityFamilyNumberRd(fid,mName,dt,it,MED_NODE,MED_NONE,_fam_nodes->getPointer());
+      if(!mrs || mrs->isNodeFamilyFieldReading())
+        {
+          _fam_nodes=DataArrayInt::New();
+          _fam_nodes->alloc(nbOfElt,1);
+          MEDmeshEntityFamilyNumberRd(fid,mName,dt,it,MED_NODE,MED_NONE,_fam_nodes->getPointer());
+        }
     }
   nbOfElt=MEDmeshnEntity(fid,mName,dt,it,MED_NODE,MED_NONE,MED_NUMBER,MED_NODAL,&chgt,&trsf);
   if(nbOfElt>0)
     {
-      _num_nodes=DataArrayInt::New();
-      _num_nodes->alloc(nbOfElt,1);
-      MEDmeshEntityNumberRd(fid,mName,dt,it,MED_NODE,MED_NONE,_num_nodes->getPointer());
+      if(!mrs || mrs->isNodeNumFieldReading())
+        {
+          _num_nodes=DataArrayInt::New();
+          _num_nodes->alloc(nbOfElt,1);
+          MEDmeshEntityNumberRd(fid,mName,dt,it,MED_NODE,MED_NONE,_num_nodes->getPointer());
+        }
     }
   int meshDim=getStructuredMesh()->getMeshDimension();
   med_geometry_type geoTypeReq=GetGeoTypeFromMeshDim(meshDim);
   nbOfElt=MEDmeshnEntity(fid,mName,dt,it,MED_CELL,geoTypeReq,MED_FAMILY_NUMBER,MED_NODAL,&chgt,&trsf);
   if(nbOfElt>0)
     {
-      _fam_cells=DataArrayInt::New();
-      _fam_cells->alloc(nbOfElt,1);
-      MEDmeshEntityFamilyNumberRd(fid,mName,dt,it,MED_CELL,geoTypeReq,_fam_cells->getPointer());
+      if(!mrs || mrs->isCellFamilyFieldReading())
+        {
+          _fam_cells=DataArrayInt::New();
+          _fam_cells->alloc(nbOfElt,1);
+          MEDmeshEntityFamilyNumberRd(fid,mName,dt,it,MED_CELL,geoTypeReq,_fam_cells->getPointer());
+        }
     }
   nbOfElt=MEDmeshnEntity(fid,mName,dt,it,MED_CELL,geoTypeReq,MED_NUMBER,MED_NODAL,&chgt,&trsf);
   if(nbOfElt>0)
     {
-      _num_cells=DataArrayInt::New();
-      _num_cells->alloc(nbOfElt,1);
-      MEDmeshEntityNumberRd(fid,mName,dt,it,MED_CELL,geoTypeReq,_num_cells->getPointer());
+      if(!mrs || mrs->isCellNumFieldReading())
+        {
+          _num_cells=DataArrayInt::New();
+          _num_cells->alloc(nbOfElt,1);
+          MEDmeshEntityNumberRd(fid,mName,dt,it,MED_CELL,geoTypeReq,_num_cells->getPointer());
+        }
     }
   nbOfElt=MEDmeshnEntity(fid,mName,dt,it,MED_CELL,geoTypeReq,MED_NAME,MED_NODAL,&chgt,&trsf);
   if(nbOfElt>0)
     {
-      _names_cells=DataArrayAsciiChar::New();
-      _names_cells->alloc(nbOfElt+1,MED_SNAME_SIZE);//not a bug to avoid the memory corruption due to last \0 at the end
-      MEDmeshEntityNameRd(fid,mName,dt,it,MED_CELL,geoTypeReq,_names_cells->getPointer());
-      _names_cells->reAlloc(nbOfElt);//not a bug to avoid the memory corruption due to last \0 at the end
+      if(!mrs || mrs->isCellNameFieldReading())
+        {
+          _names_cells=DataArrayAsciiChar::New();
+          _names_cells->alloc(nbOfElt+1,MED_SNAME_SIZE);//not a bug to avoid the memory corruption due to last \0 at the end
+          MEDmeshEntityNameRd(fid,mName,dt,it,MED_CELL,geoTypeReq,_names_cells->getPointer());
+          _names_cells->reAlloc(nbOfElt);//not a bug to avoid the memory corruption due to last \0 at the end
+        }
     }
   nbOfElt=MEDmeshnEntity(fid,mName,dt,it,MED_NODE,MED_NONE,MED_NAME,MED_NODAL,&chgt,&trsf);
   if(nbOfElt>0)
     {
-      _names_nodes=DataArrayAsciiChar::New();
-      _names_nodes->alloc(nbOfElt+1,MED_SNAME_SIZE);//not a bug to avoid the memory corruption due to last \0 at the end
-      MEDmeshEntityNameRd(fid,mName,dt,it,MED_NODE,MED_NONE,_names_nodes->getPointer());
-      _names_nodes->reAlloc(nbOfElt);//not a bug to avoid the memory corruption due to last \0 at the end
+      if(!mrs || mrs->isNodeNameFieldReading())
+        {
+          _names_nodes=DataArrayAsciiChar::New();
+          _names_nodes->alloc(nbOfElt+1,MED_SNAME_SIZE);//not a bug to avoid the memory corruption due to last \0 at the end
+          MEDmeshEntityNameRd(fid,mName,dt,it,MED_NODE,MED_NONE,_names_nodes->getPointer());
+          _names_nodes->reAlloc(nbOfElt);//not a bug to avoid the memory corruption due to last \0 at the end
+        }
     }
 }
 
@@ -4098,7 +4557,7 @@ MEDFileCMesh *MEDFileCMesh::New()
  *  \throw If there is no meshes in the file.
  *  \throw If the mesh in the file is not a Cartesian one.
  */
-MEDFileCMesh *MEDFileCMesh::New(const char *fileName) throw(INTERP_KERNEL::Exception)
+MEDFileCMesh *MEDFileCMesh::New(const char *fileName, MEDFileMeshReadSelector *mrs) throw(INTERP_KERNEL::Exception)
 {
   std::vector<std::string> ms=MEDLoader::GetMeshNames(fileName);
   if(ms.empty())
@@ -4112,7 +4571,7 @@ MEDFileCMesh *MEDFileCMesh::New(const char *fileName) throw(INTERP_KERNEL::Excep
   ParaMEDMEM::MEDCouplingMeshType meshType;
   std::string dummy2;
   MEDFileMeshL2::GetMeshIdFromName(fid,ms.front().c_str(),meshType,dt,it,dummy2);
-  return new MEDFileCMesh(fid,ms.front().c_str(),dt,it);
+  return new MEDFileCMesh(fid,ms.front().c_str(),dt,it,mrs);
 }
 
 /*!
@@ -4129,11 +4588,11 @@ MEDFileCMesh *MEDFileCMesh::New(const char *fileName) throw(INTERP_KERNEL::Excep
  *  \throw If there is no mesh with given attributes in the file.
  *  \throw If the mesh in the file is not a Cartesian one.
  */
-MEDFileCMesh *MEDFileCMesh::New(const char *fileName, const char *mName, int dt, int it) throw(INTERP_KERNEL::Exception)
+MEDFileCMesh *MEDFileCMesh::New(const char *fileName, const char *mName, int dt, int it, MEDFileMeshReadSelector *mrs) throw(INTERP_KERNEL::Exception)
 {
   MEDFileUtilities::CheckFileForRead(fileName);
   MEDFileUtilities::AutoFid fid=MEDfileOpen(fileName,MED_ACC_RDONLY);
-  return new MEDFileCMesh(fid,mName,dt,it);
+  return new MEDFileCMesh(fid,mName,dt,it,mrs);
 }
 
 std::size_t MEDFileCMesh::getHeapMemorySize() const
@@ -4180,6 +4639,11 @@ MEDFileMesh *MEDFileCMesh::shallowCpy() const throw(INTERP_KERNEL::Exception)
   return ret.retn();
 }
 
+MEDFileMesh *MEDFileCMesh::createNewEmpty() const throw(INTERP_KERNEL::Exception)
+{
+  return new MEDFileCMesh;
+}
+
 MEDFileMesh *MEDFileCMesh::deepCpy() const throw(INTERP_KERNEL::Exception)
 {
   MEDCouplingAutoRefCountObjectPtr<MEDFileCMesh> ret=new MEDFileCMesh(*this);
@@ -4240,17 +4704,17 @@ MEDFileCMesh::MEDFileCMesh()
 {
 }
 
-MEDFileCMesh::MEDFileCMesh(med_idt fid, const char *mName, int dt, int it) throw(INTERP_KERNEL::Exception)
+MEDFileCMesh::MEDFileCMesh(med_idt fid, const char *mName, int dt, int it, MEDFileMeshReadSelector *mrs) throw(INTERP_KERNEL::Exception)
 try
   {
-    loadCMeshFromFile(fid,mName,dt,it);
+    loadCMeshFromFile(fid,mName,dt,it,mrs);
   }
 catch(INTERP_KERNEL::Exception& e)
   {
     throw e;
   }
 
-void MEDFileCMesh::loadCMeshFromFile(med_idt fid, const char *mName, int dt, int it) throw(INTERP_KERNEL::Exception)
+void MEDFileCMesh::loadCMeshFromFile(med_idt fid, const char *mName, int dt, int it, MEDFileMeshReadSelector *mrs) throw(INTERP_KERNEL::Exception)
 {
   ParaMEDMEM::MEDCouplingMeshType meshType;
   int dummy0,dummy1;
@@ -4266,7 +4730,7 @@ void MEDFileCMesh::loadCMeshFromFile(med_idt fid, const char *mName, int dt, int
   MEDCouplingCMesh *mesh=loaderl2.getMesh();
   mesh->incrRef();
   _cmesh=mesh;
-  loadStrMeshFromFile(&loaderl2,fid,mName,dt,it);
+  loadStrMeshFromFile(&loaderl2,fid,mName,dt,it,mrs);
 }
 
 /*!
@@ -4347,7 +4811,7 @@ MEDFileCurveLinearMesh *MEDFileCurveLinearMesh::New()
   return new MEDFileCurveLinearMesh;
 }
 
-MEDFileCurveLinearMesh *MEDFileCurveLinearMesh::New(const char *fileName) throw(INTERP_KERNEL::Exception)
+MEDFileCurveLinearMesh *MEDFileCurveLinearMesh::New(const char *fileName, MEDFileMeshReadSelector *mrs) throw(INTERP_KERNEL::Exception)
 {
   std::vector<std::string> ms=MEDLoader::GetMeshNames(fileName);
   if(ms.empty())
@@ -4361,14 +4825,14 @@ MEDFileCurveLinearMesh *MEDFileCurveLinearMesh::New(const char *fileName) throw(
   ParaMEDMEM::MEDCouplingMeshType meshType;
   std::string dummy2;
   MEDFileMeshL2::GetMeshIdFromName(fid,ms.front().c_str(),meshType,dt,it,dummy2);
-  return new MEDFileCurveLinearMesh(fid,ms.front().c_str(),dt,it);
+  return new MEDFileCurveLinearMesh(fid,ms.front().c_str(),dt,it,mrs);
 }
 
-MEDFileCurveLinearMesh *MEDFileCurveLinearMesh::New(const char *fileName, const char *mName, int dt, int it) throw(INTERP_KERNEL::Exception)
+MEDFileCurveLinearMesh *MEDFileCurveLinearMesh::New(const char *fileName, const char *mName, int dt, int it, MEDFileMeshReadSelector *mrs) throw(INTERP_KERNEL::Exception)
 {
   MEDFileUtilities::CheckFileForRead(fileName);
   MEDFileUtilities::AutoFid fid=MEDfileOpen(fileName,MED_ACC_RDONLY);
-  return new MEDFileCurveLinearMesh(fid,mName,dt,it);
+  return new MEDFileCurveLinearMesh(fid,mName,dt,it,mrs);
 }
 
 std::size_t MEDFileCurveLinearMesh::getHeapMemorySize() const
@@ -4385,6 +4849,11 @@ MEDFileMesh *MEDFileCurveLinearMesh::shallowCpy() const throw(INTERP_KERNEL::Exc
   return ret.retn();
 }
 
+MEDFileMesh *MEDFileCurveLinearMesh::createNewEmpty() const throw(INTERP_KERNEL::Exception)
+{
+  return new MEDFileCurveLinearMesh;
+}
+
 MEDFileMesh *MEDFileCurveLinearMesh::deepCpy() const throw(INTERP_KERNEL::Exception)
 {
   MEDCouplingAutoRefCountObjectPtr<MEDFileCurveLinearMesh> ret=new MEDFileCurveLinearMesh(*this);
@@ -4483,10 +4952,10 @@ MEDFileCurveLinearMesh::MEDFileCurveLinearMesh()
 {
 }
 
-MEDFileCurveLinearMesh::MEDFileCurveLinearMesh(med_idt fid, const char *mName, int dt, int it) throw(INTERP_KERNEL::Exception)
+MEDFileCurveLinearMesh::MEDFileCurveLinearMesh(med_idt fid, const char *mName, int dt, int it, MEDFileMeshReadSelector *mrs) throw(INTERP_KERNEL::Exception)
 try
   {
-    loadCLMeshFromFile(fid,mName,dt,it);
+    loadCLMeshFromFile(fid,mName,dt,it,mrs);
   }
 catch(INTERP_KERNEL::Exception& e)
   {
@@ -4527,7 +4996,7 @@ void MEDFileCurveLinearMesh::writeLL(med_idt fid) const throw(INTERP_KERNEL::Exc
   MEDFileStructuredMesh::writeStructuredLL(fid,maa);
 }
 
-void MEDFileCurveLinearMesh::loadCLMeshFromFile(med_idt fid, const char *mName, int dt, int it) throw(INTERP_KERNEL::Exception)
+void MEDFileCurveLinearMesh::loadCLMeshFromFile(med_idt fid, const char *mName, int dt, int it, MEDFileMeshReadSelector *mrs) throw(INTERP_KERNEL::Exception)
 {
   ParaMEDMEM::MEDCouplingMeshType meshType;
   int dummy0,dummy1;
@@ -4543,7 +5012,7 @@ void MEDFileCurveLinearMesh::loadCLMeshFromFile(med_idt fid, const char *mName,
   MEDCouplingCurveLinearMesh *mesh=loaderl2.getMesh();
   mesh->incrRef();
   _clmesh=mesh;
-  loadStrMeshFromFile(&loaderl2,fid,mName,dt,it);
+  loadStrMeshFromFile(&loaderl2,fid,mName,dt,it,mrs);
 }
 
 MEDFileMeshMultiTS *MEDFileMeshMultiTS::New()
@@ -4581,7 +5050,7 @@ std::size_t MEDFileMeshMultiTS::getHeapMemorySize() const
   return ret;
 }
 
-const char *MEDFileMeshMultiTS::getName() const throw(INTERP_KERNEL::Exception)
+std::string MEDFileMeshMultiTS::getName() const throw(INTERP_KERNEL::Exception)
 {
   if(_mesh_one_ts.empty())
     throw INTERP_KERNEL::Exception("MEDFileMeshMultiTS::getName : no time steps set !");