Salome HOME
Safe call of MEDfile functions.
[modules/med.git] / src / MEDLoader / MEDFileMesh.cxx
index 987e61bd07dd86be49611719a5a66419c9c4e603..b2a610fbbee11fef798cf3fcaff0931ae75d57da 100644 (file)
@@ -1,9 +1,9 @@
-// Copyright (C) 2007-2012  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
 // License as published by the Free Software Foundation; either
-// version 2.1 of the License.
+// version 2.1 of the License, or (at your option) any later version.
 //
 // This library is distributed in the hope that it will be useful,
 // but WITHOUT ANY WARRANTY; without even the implied warranty of
 
 #include "MEDFileMesh.hxx"
 #include "MEDFileUtilities.hxx"
+#include "MEDFileFieldOverView.hxx"
+#include "MEDFileField.hxx"
 #include "MEDLoader.hxx"
+#include "MEDFileSafeCaller.txx"
 #include "MEDLoaderBase.hxx"
 
 #include "MEDCouplingUMesh.hxx"
 #include <limits>
 #include <cmath>
 
+extern med_geometry_type typmai3[34];
+
 using namespace ParaMEDMEM;
 
 const char MEDFileMesh::DFT_FAM_NAME[]="FAMILLE_ZERO";
 
-MEDFileMesh::MEDFileMesh():_order(-1),_iteration(-1),_time(0.)
+MEDFileMesh::MEDFileMesh():_order(-1),_iteration(-1),_time(0.),_univ_wr_status(true)
 {
 }
 
-std::size_t MEDFileMesh::getHeapMemorySize() const
+std::size_t MEDFileMesh::getHeapMemorySizeWithoutChildren() const
 {
-  std::size_t ret=_dt_unit.capacity()+_name.capacity()+_univ_name.capacity()+_desc_name.capacity();
+  std::size_t ret(_dt_unit.capacity()+_name.capacity()+_univ_name.capacity()+_desc_name.capacity());
   for(std::map<std::string, std::vector<std::string> >::const_iterator it=_groups.begin();it!=_groups.end();it++)
     {
       ret+=(*it).first.capacity()+(*it).second.capacity()*sizeof(std::string);
@@ -52,7 +57,22 @@ std::size_t MEDFileMesh::getHeapMemorySize() const
   return ret;
 }
 
-MEDFileMesh *MEDFileMesh::New(const char *fileName) throw(INTERP_KERNEL::Exception)
+std::vector<const BigMemoryObject *> MEDFileMesh::getDirectChildrenWithNull() const
+{
+  return std::vector<const BigMemoryObject *>();
+}
+
+/*!
+ * Returns a new MEDFileMesh holding the mesh data that has been read from a given MED
+ * file. The first mesh in the file is loaded.
+ *  \param [in] fileName - the name of MED file to read.
+ *  \return MEDFileMesh * - a new instance of MEDFileMesh. The caller is to delete this
+ *          mesh using decrRef() as it is no more needed. 
+ *  \throw If the file is not readable.
+ *  \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 std::string& fileName, MEDFileMeshReadSelector *mrs)
 {
   std::vector<std::string> ms=MEDLoader::GetMeshNames(fileName);
   if(ms.empty())
@@ -62,69 +82,105 @@ MEDFileMesh *MEDFileMesh::New(const char *fileName) throw(INTERP_KERNEL::Excepti
     }
   MEDFileUtilities::CheckFileForRead(fileName);
   ParaMEDMEM::MEDCouplingMeshType meshType;
-  MEDFileUtilities::AutoFid fid=MEDfileOpen(fileName,MED_ACC_RDONLY);
+  MEDFileUtilities::AutoFid fid=MEDfileOpen(fileName.c_str(),MED_ACC_RDONLY);
   int dt,it;
   std::string dummy2;
-  MEDFileMeshL2::GetMeshIdFromName(fid,ms.front().c_str(),meshType,dt,it,dummy2);
+  MEDFileMeshL2::GetMeshIdFromName(fid,ms.front(),meshType,dt,it,dummy2);
   switch(meshType)
-    {
+  {
     case UNSTRUCTURED:
       {
         MEDCouplingAutoRefCountObjectPtr<MEDFileUMesh> ret=MEDFileUMesh::New();
-        ret->loadUMeshFromFile(fid,ms.front().c_str(),dt,it);
+        ret->loadUMeshFromFile(fid,ms.front(),dt,it,mrs);
+        ret->loadJointsFromFile(fid);
         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(),dt,it,mrs);
+        ret->loadJointsFromFile(fid);
         return (MEDFileCMesh *)ret.retn();
       }
     case CURVE_LINEAR:
       {
         MEDCouplingAutoRefCountObjectPtr<MEDFileCurveLinearMesh> ret=MEDFileCurveLinearMesh::New();
-        ret->loadCLMeshFromFile(fid,ms.front().c_str(),dt,it);
-        return (MEDFileCMesh *)ret.retn();
+        ret->loadCLMeshFromFile(fid,ms.front(),dt,it,mrs);
+        ret->loadJointsFromFile(fid);
+        return (MEDFileCurveLinearMesh *)ret.retn();
       }
     default:
       {
         std::ostringstream oss; oss << "MEDFileMesh::New : MED file exists and has mesh '" << ms.front() << "' exists but unsupported type yet !";
         throw INTERP_KERNEL::Exception(oss.str().c_str());
       }
-    }
+  }
 }
 
-MEDFileMesh *MEDFileMesh::New(const char *fileName, const char *mName, int dt, int it) throw(INTERP_KERNEL::Exception)
+/*!
+ * Returns a new MEDFileMesh holding the mesh data that has been read from a given MED
+ * file. The mesh to load is specified by its name and numbers of a time step and an
+ * iteration.
+ *  \param [in] fileName - the name of MED file to read.
+ *  \param [in] mName - the name of the mesh to read.
+ *  \param [in] dt - the number of a time step.
+ *  \param [in] it - the number of an iteration.
+ *  \param [in] joints - the sub-domain joints to use instead of those that can be read
+ *          from the MED file. Usually this joints are those just read by another iteration
+ *          of mName mesh, when this method is called by MEDFileMeshMultiTS::New()
+ *  \return MEDFileMesh * - a new instance of MEDFileMesh. The caller is to delete this
+ *          mesh using decrRef() as it is no more needed. 
+ *  \throw If the file is not readable.
+ *  \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 std::string& fileName, const std::string& mName, int dt, int it, MEDFileMeshReadSelector *mrs, MEDFileJoints* joints)
 {
   MEDFileUtilities::CheckFileForRead(fileName);
   ParaMEDMEM::MEDCouplingMeshType meshType;
-  MEDFileUtilities::AutoFid fid=MEDfileOpen(fileName,MED_ACC_RDONLY);
+  MEDFileUtilities::AutoFid fid=MEDfileOpen(fileName.c_str(),MED_ACC_RDONLY);
   int dummy0,dummy1;
   std::string dummy2;
   MEDFileMeshL2::GetMeshIdFromName(fid,mName,meshType,dummy0,dummy1,dummy2);
   switch(meshType)
-    {
+  {
     case UNSTRUCTURED:
       {
         MEDCouplingAutoRefCountObjectPtr<MEDFileUMesh> ret=MEDFileUMesh::New();
-        ret->loadUMeshFromFile(fid,mName,dt,it);
+        ret->loadUMeshFromFile(fid,mName,dt,it,mrs);
+        ret->loadJointsFromFile(fid,joints);
         return (MEDFileUMesh *)ret.retn();
       }
     case CARTESIAN:
       {
         MEDCouplingAutoRefCountObjectPtr<MEDFileCMesh> ret=MEDFileCMesh::New();
-        ret->loadCMeshFromFile(fid,mName,dt,it);
+        ret->loadCMeshFromFile(fid,mName,dt,it,mrs);
+        ret->loadJointsFromFile(fid,joints);
         return (MEDFileCMesh *)ret.retn();
       }
+    case CURVE_LINEAR:
+      {
+        MEDCouplingAutoRefCountObjectPtr<MEDFileCurveLinearMesh> ret=MEDFileCurveLinearMesh::New();
+        ret->loadCLMeshFromFile(fid,mName,dt,it,mrs);
+        ret->loadJointsFromFile(fid,joints);
+        return (MEDFileCurveLinearMesh *)ret.retn();
+      }
     default:
       {
         std::ostringstream oss; oss << "MEDFileMesh::New : MED file exists and has mesh '" << mName << "' exists but unsupported type yet !";
         throw INTERP_KERNEL::Exception(oss.str().c_str());
       }
-    }
+  }
 }
 
-void MEDFileMesh::write(med_idt fid) const throw(INTERP_KERNEL::Exception)
+/*!
+ * Writes \a this mesh into an open MED file specified by its descriptor.
+ *  \param [in] fid - the MED file descriptor.
+ *  \throw If the mesh name is not set.
+ *  \throw If the file is open for reading only.
+ *  \throw If the writing mode == 1 and the same data is present in an existing file.
+ */
+void MEDFileMesh::write(med_idt fid) const
 {
   if(!existsFamily(0))
     const_cast<MEDFileMesh *>(this)->addFamily(DFT_FAM_NAME,0);
@@ -133,15 +189,32 @@ void MEDFileMesh::write(med_idt fid) const throw(INTERP_KERNEL::Exception)
   writeLL(fid);
 }
 
-void MEDFileMesh::write(const char *fileName, int mode) const throw(INTERP_KERNEL::Exception)
+/*!
+ * Writes \a this mesh into a MED file specified by its name.
+ *  \param [in] fileName - the MED file name.
+ *  \param [in] mode - the writing mode. For more on \a mode, see \ref AdvMEDLoaderBasics.
+ * - 2 - erase; an existing file is removed.
+ * - 1 - append; same data should not be present in an existing file.
+ * - 0 - overwrite; same data present in an existing file is overwritten.
+ *  \throw If the mesh name is not set.
+ *  \throw If \a mode == 1 and the same data is present in an existing file.
+ */
+void MEDFileMesh::write(const std::string& fileName, int mode) const
 {
   med_access_mode medmod=MEDFileUtilities::TraduceWriteMode(mode);
-  MEDFileUtilities::AutoFid fid=MEDfileOpen(fileName,medmod);
+  MEDFileUtilities::AutoFid fid=MEDfileOpen(fileName.c_str(),medmod);
   std::ostringstream oss; oss << "MEDFileMesh : error on attempt to write in file : \"" << fileName << "\""; 
-  MEDFileUtilities::CheckMEDCode(fid,fid,oss.str().c_str());
+  MEDFileUtilities::CheckMEDCode(fid,fid,oss.str());
   write(fid);
 }
 
+/*!
+ * Checks if \a this and another mesh are equal.
+ *  \param [in] other - the mesh to compare with.
+ *  \param [in] eps - a precision used to compare real values.
+ *  \param [in,out] what - the string returning description of unequal data.
+ *  \return bool - \c true if the meshes are equal, \c false, else.
+ */
 bool MEDFileMesh::isEqual(const MEDFileMesh *other, double eps, std::string& what) const
 {
   if(_order!=other->_order)
@@ -169,11 +242,7 @@ bool MEDFileMesh::isEqual(const MEDFileMesh *other, double eps, std::string& wha
       what="Names differ !";
       return false;
     }
-  if(_univ_name!=other->_univ_name)
-    {
-      what="Univ names differ !";
-      return false;
-    }
+  //univ_name has been ignored -> not a bug because it is a mutable attribute
   if(_desc_name!=other->_desc_name)
     {
       what="Description names differ !";
@@ -186,12 +255,20 @@ bool MEDFileMesh::isEqual(const MEDFileMesh *other, double eps, std::string& wha
   return true;
 }
 
+void MEDFileMesh::setName(const std::string& name)
+{
+  _name=name;
+}
+
+/*!
+ * Clears redundant attributes of incorporated data arrays.
+ */
 void MEDFileMesh::clearNonDiscrAttributes() const
 {
-  
+
 }
 
-bool MEDFileMesh::changeNames(const std::vector< std::pair<std::string,std::string> >& modifTab) throw(INTERP_KERNEL::Exception)
+bool MEDFileMesh::changeNames(const std::vector< std::pair<std::string,std::string> >& modifTab)
 {
   for(std::vector< std::pair<std::string,std::string> >::const_iterator it=modifTab.begin();it!=modifTab.end();it++)
     {
@@ -204,19 +281,68 @@ bool MEDFileMesh::changeNames(const std::vector< std::pair<std::string,std::stri
   return false;
 }
 
+/*!
+ * Copies data on groups and families from another mesh.
+ *  \param [in] other - the mesh to copy the data from.
+ */
 void MEDFileMesh::copyFamGrpMapsFrom(const MEDFileMesh& other)
 {
   _groups=other._groups;
   _families=other._families;
 }
 
-std::vector<std::string> MEDFileMesh::getFamiliesOnGroup(const char *name) const throw(INTERP_KERNEL::Exception)
+
+/*!
+ * This method clear all the groups in the map.
+ * So this method does not operate at all on arrays.
+ * So this method can lead to orphan families.
+ * 
+ * \sa MEDFileMesh::clearFamMap, MEDFileMesh::clearFamGrpMaps
+ */
+void MEDFileMesh::clearGrpMap()
+{
+  _groups.clear();
+}
+
+/*!
+ * This method clear all the families in the map.
+ * So this method does not operate at all on arrays.
+ * WARNING ! if there are some groups lying on cleared families, those groups will be impacted !
+ *
+ * \sa MEDFileMesh::clearFamMap, MEDFileMesh::clearFamGrpMaps
+ */
+void MEDFileMesh::clearFamMap()
+{
+  _families.clear();
+}
+
+/*!
+ * This method clear all the families and groups in the map.
+ * So this method does not operate at all on arrays.
+ * As all groups and families entry will be removed after 
+ * the call of MEDFileMesh::setFamilyFieldArr method with 0 or None (python) in the 2nd parameter can be useful to reduce the size of the object.
+ *
+ * \sa MEDFileMesh::clearFamMap, MEDFileMesh::clearFamMap
+ */
+void MEDFileMesh::clearFamGrpMaps()
+{
+  clearGrpMap();
+  clearFamMap();
+}
+
+/*!
+ * Returns names of families constituting a group.
+ *  \param [in] name - the name of the group of interest.
+ *  \return std::vector<std::string> - a sequence of names of the families.
+ *  \throw If the name of a nonexistent group is specified.
+ */
+std::vector<std::string> MEDFileMesh::getFamiliesOnGroup(const std::string& name) const
 {
   std::string oname(name);
   std::map<std::string, std::vector<std::string> >::const_iterator it=_groups.find(oname);
-  std::vector<std::string> grps=getGroupsNames();
   if(it==_groups.end())
     {
+      std::vector<std::string> grps=getGroupsNames();
       std::ostringstream oss; oss << "No such groupname \"" << name << "\" !\nAvailable groups are :";
       std::copy(grps.begin(),grps.end(),std::ostream_iterator<std::string>(oss," "));
       throw INTERP_KERNEL::Exception(oss.str().c_str());
@@ -224,7 +350,13 @@ std::vector<std::string> MEDFileMesh::getFamiliesOnGroup(const char *name) const
   return (*it).second;
 }
 
-std::vector<std::string> MEDFileMesh::getFamiliesOnGroups(const std::vector<std::string>& grps) const throw(INTERP_KERNEL::Exception)
+/*!
+ * Returns names of families constituting some groups.
+ *  \param [in] grps - a sequence of names of groups of interest.
+ *  \return std::vector<std::string> - a sequence of names of the families.
+ *  \throw If a name of a nonexistent group is present in \a grps.
+ */
+std::vector<std::string> MEDFileMesh::getFamiliesOnGroups(const std::vector<std::string>& grps) const
 {
   std::set<std::string> fams;
   for(std::vector<std::string>::const_iterator it=grps.begin();it!=grps.end();it++)
@@ -243,7 +375,13 @@ std::vector<std::string> MEDFileMesh::getFamiliesOnGroups(const std::vector<std:
   return fams2;
 }
 
-std::vector<int> MEDFileMesh::getFamiliesIdsOnGroup(const char *name) const throw(INTERP_KERNEL::Exception)
+/*!
+ * Returns ids of families constituting a group.
+ *  \param [in] name - the name of the group of interest.
+ *  \return std::vector<int> - sequence of ids of the families.
+ *  \throw If the name of a nonexistent group is specified.
+ */
+std::vector<int> MEDFileMesh::getFamiliesIdsOnGroup(const std::string& name) const
 {
   std::string oname(name);
   std::map<std::string, std::vector<std::string> >::const_iterator it=_groups.find(oname);
@@ -258,10 +396,13 @@ std::vector<int> MEDFileMesh::getFamiliesIdsOnGroup(const char *name) const thro
 }
 
 /*!
- * This method sets families at a corresponding groups existing or not. If it existed, it is replaced by new 'fams'.
- * Each entry in 'fams' is checked if it is not still existing default id 0 is set.
+ * Sets names of families constituting a group. If data on families of this group is
+ * already present, it is overwritten. Every family in \a fams is checked, and if a
+ family is not yet in \a this mesh, the default group id \c 0 is assigned to it.
+ *  \param [in] name - the name of the group of interest.
+ *  \param [in] fams - a sequence of names of families constituting the group.
  */
-void MEDFileMesh::setFamiliesOnGroup(const char *name, const std::vector<std::string>& fams) throw(INTERP_KERNEL::Exception)
+void MEDFileMesh::setFamiliesOnGroup(const std::string& name, const std::vector<std::string>& fams)
 {
   std::string oname(name);
   _groups[oname]=fams;
@@ -274,10 +415,14 @@ void MEDFileMesh::setFamiliesOnGroup(const char *name, const std::vector<std::st
 }
 
 /*!
- * Behaves as MEDFileMesh::setFamiliesOnGroup, except that if there is presence of a family id in 'famIds' not existing an exception is thrown.
- * If several families have same id the first one in lexical order is taken into account.
+ * Sets families constituting a group. The families are specified by their ids.
+ * If a family name is not found by its id, an exception is thrown.
+ * If several families have same id, the first one in lexical order is taken.
+ *  \param [in] name - the name of the group of interest.
+ *  \param [in] famIds - a sequence of ids of families constituting the group.
+ *  \throw If a family name is not found by its id.
  */
-void MEDFileMesh::setFamiliesIdsOnGroup(const char *name, const std::vector<int>& famIds) throw(INTERP_KERNEL::Exception)
+void MEDFileMesh::setFamiliesIdsOnGroup(const std::string& name, const std::vector<int>& famIds)
 {
   std::string oname(name);
   std::vector<std::string> fams(famIds.size());
@@ -290,7 +435,12 @@ void MEDFileMesh::setFamiliesIdsOnGroup(const char *name, const std::vector<int>
   _groups[oname]=fams;
 }
 
-std::vector<std::string> MEDFileMesh::getGroupsOnFamily(const char *name) const throw(INTERP_KERNEL::Exception)
+/*!
+ * Returns names of groups including a given family.
+ *  \param [in] name - the name of the family of interest.
+ *  \return std::vector<std::string> - a sequence of names of groups including the family.
+ */
+std::vector<std::string> MEDFileMesh::getGroupsOnFamily(const std::string& name) const
 {
   std::vector<std::string> ret;
   for(std::map<std::string, std::vector<std::string> >::const_iterator it1=_groups.begin();it1!=_groups.end();it1++)
@@ -306,9 +456,12 @@ std::vector<std::string> MEDFileMesh::getGroupsOnFamily(const char *name) const
 }
 
 /*!
- * This method expects that family 'famName' is already existing. If not an exception will be thrown.
+ * Adds an existing family to groups.
+ *  \param [in] famName - a name of family to add to \a grps.
+ *  \param [in] grps - a sequence of group names to add the family in.
+ *  \throw If a family named \a famName not yet exists.
  */
-void MEDFileMesh::setGroupsOnFamily(const char *famName, const std::vector<std::string>& grps) throw(INTERP_KERNEL::Exception)
+void MEDFileMesh::setGroupsOnFamily(const std::string& famName, const std::vector<std::string>& grps)
 {
   std::string fName(famName);
   const std::map<std::string,int>::const_iterator it=_families.find(fName);
@@ -332,6 +485,10 @@ void MEDFileMesh::setGroupsOnFamily(const char *famName, const std::vector<std::
     }
 }
 
+/*!
+ * Returns names of all groups of \a this mesh.
+ *  \return std::vector<std::string> - a sequence of group names.
+ */
 std::vector<std::string> MEDFileMesh::getGroupsNames() const
 {
   std::vector<std::string> ret(_groups.size());
@@ -341,6 +498,10 @@ std::vector<std::string> MEDFileMesh::getGroupsNames() const
   return ret;
 }
 
+/*!
+ * Returns names of all families of \a this mesh.
+ *  \return std::vector<std::string> - a sequence of family names.
+ */
 std::vector<std::string> MEDFileMesh::getFamiliesNames() const
 {
   std::vector<std::string> ret(_families.size());
@@ -351,15 +512,16 @@ std::vector<std::string> MEDFileMesh::getFamiliesNames() const
 }
 
 /*!
- * This method scans every families and for each families shared by only one group, the corresponding family takes the same name than the group.
+ * Changes a name of every family, included in one group only, to be same as the group name.
+ *  \throw If there are families with equal names in \a this mesh.
  */
-void MEDFileMesh::assignFamilyNameWithGroupName() throw(INTERP_KERNEL::Exception)
+void MEDFileMesh::assignFamilyNameWithGroupName()
 {
   std::map<std::string, std::vector<std::string> > groups(_groups);
   std::map<std::string,int> newFams;
   for(std::map<std::string,int>::const_iterator it=_families.begin();it!=_families.end();it++)
     {
-      std::vector<std::string> grps=getGroupsOnFamily((*it).first.c_str());
+      std::vector<std::string> grps=getGroupsOnFamily((*it).first);
       if(grps.size()==1 && groups[grps[0]].size()==1)
         {
           if(newFams.find(grps[0])!=newFams.end())
@@ -386,7 +548,33 @@ void MEDFileMesh::assignFamilyNameWithGroupName() throw(INTERP_KERNEL::Exception
   _groups=groups;
 }
 
-void MEDFileMesh::removeGroup(const char *name) throw(INTERP_KERNEL::Exception)
+/*!
+ * 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()
+{
+  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.
+ *  \throw If no group with such a \a name exists.
+ */
+void MEDFileMesh::removeGroup(const std::string& name)
 {
   std::string oname(name);
   std::map<std::string, std::vector<std::string> >::iterator it=_groups.find(oname);
@@ -400,7 +588,12 @@ void MEDFileMesh::removeGroup(const char *name) throw(INTERP_KERNEL::Exception)
   _groups.erase(it);
 }
 
-void MEDFileMesh::removeFamily(const char *name) throw(INTERP_KERNEL::Exception)
+/*!
+ * Removes a family from \a this mesh.
+ *  \param [in] name - the name of the family to remove.
+ *  \throw If no family with such a \a name exists.
+ */
+void MEDFileMesh::removeFamily(const std::string& name)
 {
   std::string oname(name);
   std::map<std::string, int >::iterator it=_families.find(oname);
@@ -421,7 +614,145 @@ void MEDFileMesh::removeFamily(const char *name) throw(INTERP_KERNEL::Exception)
     }
 }
 
-void MEDFileMesh::changeGroupName(const char *oldName, const char *newName) 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()
+{
+  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()
+{
+  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);
+          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;
+}
+
+/*!
+ * This method operates only on maps in \a this. The arrays are not considered here. So this method will remove a family (except "FAMILLE_ZERO" family) if no group lies on it whatever
+ * this family is orphan or not.
+ *
+ * \warning this method is different from removeOrphanFamilies that scans family field array to find orphan families.
+ */
+void MEDFileMesh::removeFamiliesReferedByNoGroups()
+{
+  std::map<std::string,int> fams;
+  std::set<std::string> sfams;
+  for(std::map<std::string,int>::const_iterator it=_families.begin();it!=_families.end();it++)
+    sfams.insert((*it).first);
+  for(std::map<std::string, std::vector<std::string> >::const_iterator it0=_groups.begin();it0!=_groups.end();it0++)
+    for(std::vector<std::string>::const_iterator it1=(*it0).second.begin();it1!=(*it0).second.end();it1++)
+      sfams.erase(*it1);
+  for(std::set<std::string>::const_iterator it=sfams.begin();it!=sfams.end();it++)
+    if(*it!=DFT_FAM_NAME)
+      _families.erase(*it);
+}
+
+/*!
+ * This method has no impact on groups. This method only works on families. This method firstly removes families not refered by any groups in \a this, then all unused entities
+ * are put as belonging to family 0 ("FAMILLE_ZERO"). Finally, all orphanFamilies are killed.
+ * This method raises an exception if "FAMILLE_ZERO" is already belonging to a group.
+ *
+ * \sa MEDFileMesh::removeOrphanFamilies
+ */
+void MEDFileMesh::rearrangeFamilies()
+{
+  checkOrphanFamilyZero();
+  removeFamiliesReferedByNoGroups();
+  //
+  std::vector<int> levels(getNonEmptyLevelsExt());
+  std::set<int> idsRefed;
+  for(std::map<std::string,int>::const_iterator it=_families.begin();it!=_families.end();it++)
+    idsRefed.insert((*it).second);
+  for(std::vector<int>::const_iterator it=levels.begin();it!=levels.end();it++)
+    {
+      const DataArrayInt *fams(0);
+      try
+      {
+          fams=getFamilyFieldAtLevel(*it);
+      }
+      catch(INTERP_KERNEL::Exception& e) { }
+      if(!fams)
+        continue;
+      std::vector<bool> v(fams->getNumberOfTuples(),false);
+      for(std::set<int>::const_iterator pt=idsRefed.begin();pt!=idsRefed.end();pt++)
+        fams->switchOnTupleEqualTo(*pt,v);
+      MEDCouplingAutoRefCountObjectPtr<DataArrayInt> unfetchedIds(DataArrayInt::BuildListOfSwitchedOff(v));
+      if(!unfetchedIds->empty())
+        {
+          MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newFams(fams->deepCpy());
+          newFams->setPartOfValuesSimple3(0,unfetchedIds->begin(),unfetchedIds->end(),0,1,1);
+          setFamilyFieldArr(*it,newFams);
+        }
+    }
+  removeOrphanFamilies();
+}
+
+/*!
+ * This method only checks that "FAMILLE_ZERO" is orphan (not belonging to a group).
+ */
+void MEDFileMesh::checkOrphanFamilyZero() const
+{
+  for(std::map<std::string, std::vector<std::string> >::const_iterator it=_groups.begin();it!=_groups.end();it++)
+    {
+      if(std::find((*it).second.begin(),(*it).second.end(),DFT_FAM_NAME)!=(*it).second.end())
+        {
+          std::ostringstream oss; oss << "MEDFileMesh::rearrangeFamilies : Groups \"" << (*it).first << "\" is lying on family \"" << DFT_FAM_NAME << "\" !";
+          throw INTERP_KERNEL::Exception(oss.str().c_str());
+        }
+    }
+}
+
+/*!
+ * Renames a group in \a this mesh.
+ *  \param [in] oldName - a current name of the group to rename.
+ *  \param [in] newName - a new group name.
+ *  \throw If no group named \a oldName exists in \a this mesh.
+ *  \throw If a group named \a newName already exists.
+ */
+void MEDFileMesh::changeGroupName(const std::string& oldName, const std::string& newName)
 {
   std::string oname(oldName);
   std::map<std::string, std::vector<std::string> >::iterator it=_groups.find(oname);
@@ -433,8 +764,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());
@@ -445,10 +776,12 @@ void MEDFileMesh::changeGroupName(const char *oldName, const char *newName) thro
 }
 
 /*!
- * This method changes the family ids in 'this'. It leads to a modification into '_families' attributes \b and in
- * ids stored in arrays. This method calls MEDFileMesh::changeFamilyIdArr method.
+ * Changes an id of a family in \a this mesh. 
+ * This method calls changeFamilyIdArr().
+ *  \param [in] oldId - a current id of the family.
+ *  \param [in] newId - a new family id.
  */
-void MEDFileMesh::changeFamilyId(int oldId, int newId) throw(INTERP_KERNEL::Exception)
+void MEDFileMesh::changeFamilyId(int oldId, int newId)
 {
   changeFamilyIdArr(oldId,newId);
   std::map<std::string,int> fam2;
@@ -462,7 +795,14 @@ void MEDFileMesh::changeFamilyId(int oldId, int newId) throw(INTERP_KERNEL::Exce
   _families=fam2;
 }
 
-void MEDFileMesh::changeFamilyName(const char *oldName, const char *newName) throw(INTERP_KERNEL::Exception)
+/*!
+ * Renames a family in \a this mesh.
+ *  \param [in] oldName - a current name of the family to rename.
+ *  \param [in] newName - a new family name.
+ *  \throw If no family named \a oldName exists in \a this mesh.
+ *  \throw If a family named \a newName already exists.
+ */
+void MEDFileMesh::changeFamilyName(const std::string& oldName, const std::string& newName)
 {
   std::string oname(oldName);
   std::map<std::string, int >::iterator it=_families.find(oname);
@@ -492,6 +832,13 @@ void MEDFileMesh::changeFamilyName(const char *oldName, const char *newName) thr
     }
 }
 
+/*!
+ * Checks if \a this and another mesh contains the same families.
+ *  \param [in] other - the mesh to compare with \a this one.
+ *  \param [in,out] what - an unused parameter.
+ *  \return bool - \c true if number of families and their ids are the same in the two
+ *          meshes. Families with the id == \c 0 are not considered.
+ */
 bool MEDFileMesh::areFamsEqual(const MEDFileMesh *other, std::string& what) const
 {
   if(_families==other->_families)
@@ -507,6 +854,14 @@ bool MEDFileMesh::areFamsEqual(const MEDFileMesh *other, std::string& what) cons
   return fam0==fam1;
 }
 
+/*!
+ * Checks if \a this and another mesh contains the same groups.
+ *  \param [in] other - the mesh to compare with \a this one.
+ *  \param [in,out] what - a string describing a difference of groups of the two meshes
+ *          in case if this method returns \c false.
+ *  \return bool - \c true if number of groups and families constituting them are the
+ *          same in the two meshes.
+ */
 bool MEDFileMesh::areGrpsEqual(const MEDFileMesh *other, std::string& what) const
 {
   if(_groups==other->_groups)
@@ -545,7 +900,7 @@ bool MEDFileMesh::areGrpsEqual(const MEDFileMesh *other, std::string& what) cons
         {
           oss << " Group \"" << (*it).first << "\" on following families :\n";
           for(std::vector<std::string>::const_iterator it2=(*it).second.begin();it2!=(*it).second.end();it2++)
-        oss << "    \"" << *it2 << "\n";
+            oss << "    \"" << *it2 << "\n";
         }
       oss << "Second group description :\n";
       for(std::map<std::string, std::vector<std::string> >::const_iterator it=other->_groups.begin();it!=other->_groups.end();it++)
@@ -559,12 +914,22 @@ bool MEDFileMesh::areGrpsEqual(const MEDFileMesh *other, std::string& what) cons
   return ret;
 }
 
-bool MEDFileMesh::existsGroup(const char *groupName) const
+/*!
+ * Checks if a group with a given name exists in \a this mesh.
+ *  \param [in] groupName - the group name.
+ *  \return bool - \c true the group \a groupName exists in \a this mesh.
+ */
+bool MEDFileMesh::existsGroup(const std::string& groupName) const
 {
   std::string grpName(groupName);
   return _groups.find(grpName)!=_groups.end();
 }
 
+/*!
+ * Checks if a family with a given id exists in \a this mesh.
+ *  \param [in] famId - the family id.
+ *  \return bool - \c true the family with the id \a famId exists in \a this mesh.
+ */
 bool MEDFileMesh::existsFamily(int famId) const
 {
   for(std::map<std::string,int>::const_iterator it2=_families.begin();it2!=_families.end();it2++)
@@ -573,19 +938,29 @@ bool MEDFileMesh::existsFamily(int famId) const
   return false;
 }
 
-bool MEDFileMesh::existsFamily(const char *familyName) const
+/*!
+ * Checks if a family with a given name exists in \a this mesh.
+ *  \param [in] familyName - the family name.
+ *  \return bool - \c true the family \a familyName exists in \a this mesh.
+ */
+bool MEDFileMesh::existsFamily(const std::string& familyName) const
 {
   std::string fname(familyName);
   return _families.find(fname)!=_families.end();
 }
 
-void MEDFileMesh::setFamilyId(const char *familyName, int id)
+/*!
+ * Sets an id of a family.
+ *  \param [in] familyName - the family name.
+ *  \param [in] id - a new id of the family.
+ */
+void MEDFileMesh::setFamilyId(const std::string& familyName, int id)
 {
   std::string fname(familyName);
   _families[fname]=id;
 }
 
-void MEDFileMesh::setFamilyIdUnique(const char *familyName, int id) throw(INTERP_KERNEL::Exception)
+void MEDFileMesh::setFamilyIdUnique(const std::string& familyName, int id)
 {
   std::string fname(familyName);
   for(std::map<std::string,int>::const_iterator it=_families.begin();it!=_families.end();it++)
@@ -601,23 +976,25 @@ void MEDFileMesh::setFamilyIdUnique(const char *familyName, int id) throw(INTERP
 }
 
 /*!
- * This method appends a new entry in _families attribute. An exception is thrown if either the famId is already
- * kept by an another familyName. An exception is thrown if name 'familyName' is alreadyset with a different 'famId'.
+ * Adds a family to \a this mesh.
+ *  \param [in] familyName - a name of the family.
+ *  \param [in] famId - an id of the family.
+ *  \throw If a family with the same name or id already exists in \a this mesh.
  */
-void MEDFileMesh::addFamily(const char *familyName, int famId) throw(INTERP_KERNEL::Exception)
+void MEDFileMesh::addFamily(const std::string& familyName, int famId)
 {
   std::string fname(familyName);
   std::map<std::string,int>::const_iterator it=_families.find(fname);
   if(it==_families.end())
     {
-       for(std::map<std::string,int>::const_iterator it2=_families.begin();it2!=_families.end();it2++)
-         if((*it2).second==famId)
-           {
-             std::ostringstream oss;
-             oss << "MEDFileMesh::addFamily : Family \"" << (*it2).first << "\" already exists with specified id : " << famId << " !";
-             throw INTERP_KERNEL::Exception(oss.str().c_str());
-           }
-       _families[fname]=famId;
+      for(std::map<std::string,int>::const_iterator it2=_families.begin();it2!=_families.end();it2++)
+        if((*it2).second==famId)
+          {
+            std::ostringstream oss;
+            oss << "MEDFileMesh::addFamily : Family \"" << (*it2).first << "\" already exists with specified id : " << famId << " !";
+            throw INTERP_KERNEL::Exception(oss.str().c_str());
+          }
+      _families[fname]=famId;
     }
   else
     {
@@ -631,14 +1008,19 @@ void MEDFileMesh::addFamily(const char *familyName, int famId) throw(INTERP_KERN
 }
 
 /*!
- * This method creates a new group called 'groupName' in 'this'. If it exists a group with the same name an INTERP_KERNEL::Exception will be thrown.
- * If the 'meshDimRelToMaxExt' is not existing an INTERP_KERNEL::Exception will be thrown too.
- * \b WARNING : This method does \b not garantee that 'groupName' lies only on a single level specified by 'meshDimRelToMaxExt'.
- * in the case of a presence of one or more family id in family field at 'meshDimRelToMaxExt' level that appears in another level.
- * If there is a risk of such case call MEDFileMesh::keepFamIdsOnlyOnLevs method \b before calling this method. 
- * (call to MEDFileMesh::keepFamIdsOnlyOnLevs should be done with MEDFileMesh::getFamiliesIdsOnGroup('groupName' as first input ).
+ * Creates a group including all mesh entities of given dimension.
+ * \warning This method does \b not guarantee that the created group includes mesh
+ * entities of only \a meshDimRelToMaxExt dimension in the case if some family id is
+ * present in family fields of different dimensions. To assure this, call
+ * ensureDifferentFamIdsPerLevel() \b before calling this method.
+ *  \param [in] meshDimRelToMaxExt - a relative dimension of mesh entities to include to
+ *          the group.
+ *  \param [in] groupName - a name of the new group.
+ *  \throw If a group named \a groupName already exists.
+ *  \throw If no mesh entities of dimension \a meshDimRelToMaxExt exist in \a this mesh.
+ *  \throw If no family field of dimension \a meshDimRelToMaxExt is present in \a this mesh.
  */
-void MEDFileMesh::createGroupOnAll(int meshDimRelToMaxExt, const char *groupName) throw(INTERP_KERNEL::Exception)
+void MEDFileMesh::createGroupOnAll(int meshDimRelToMaxExt, const std::string& groupName)
 {
   std::string grpName(groupName);
   std::vector<int> levs=getNonEmptyLevelsExt();
@@ -660,9 +1042,9 @@ void MEDFileMesh::createGroupOnAll(int meshDimRelToMaxExt, const char *groupName
   const DataArrayInt *fieldFamIds=getFamilyFieldAtLevel(meshDimRelToMaxExt);
   if(fieldFamIds==0)
     throw INTERP_KERNEL::Exception("MEDFileMesh::createGroupOnAll : Family field arr ids is not defined for this level !");
-  std::set<int> famIds=fieldFamIds->getDifferentValues();
+  MEDCouplingAutoRefCountObjectPtr<DataArrayInt> famIds=fieldFamIds->getDifferentValues();
   std::vector<std::string> familiesOnWholeGroup;
-  for(std::set<int>::const_iterator it=famIds.begin();it!=famIds.end();it++)
+  for(const int *it=famIds->begin();it!=famIds->end();it++)
     {
       bool tmp;
       familiesOnWholeGroup.push_back(findOrCreateAndGiveFamilyWithId(*it,tmp));
@@ -671,12 +1053,15 @@ void MEDFileMesh::createGroupOnAll(int meshDimRelToMaxExt, const char *groupName
 }
 
 /*!
- * This method checks that family Ids in 'famIds' are not present in levels \b not in 'vMeshDimRelToMaxExt'.
- * If it is the case true is returned and 'this' is not modified.
- * If there is some levels not in 'vMeshDimRelToMaxExt' where one or more family ids in 'famIds' appear
- * new families are created and groups are updated in consequence.
+ * Ensures that given family ids do not present in family fields of dimensions different
+ * than given ones. If a family id is present in the family fields of dimensions different
+ * than the given ones, a new family is created and the whole data is updated accordingly.
+ *  \param [in] famIds - a sequence of family ids to check.
+ *  \param [in] vMeshDimRelToMaxExt - a sequence of relative dimensions to which the \a
+ *          famIds should exclusively belong.
+ *  \return bool - \c true if no modification is done in \a this mesh by this method.
  */
-bool MEDFileMesh::keepFamIdsOnlyOnLevs(const std::vector<int>& famIds, const std::vector<int>& vMeshDimRelToMaxExt) throw(INTERP_KERNEL::Exception)
+bool MEDFileMesh::keepFamIdsOnlyOnLevs(const std::vector<int>& famIds, const std::vector<int>& vMeshDimRelToMaxExt)
 {
   std::set<int> levsInput(vMeshDimRelToMaxExt.begin(),vMeshDimRelToMaxExt.end());
   std::vector<int> levs=getNonEmptyLevelsExt();
@@ -694,16 +1079,16 @@ bool MEDFileMesh::keepFamIdsOnlyOnLevs(const std::vector<int>& famIds, const std
       const DataArrayInt *fieldFamIds=getFamilyFieldAtLevel(*it);
       if(fieldFamIds)
         {
-          std::set<int> famIds3=fieldFamIds->getDifferentValues();
+          MEDCouplingAutoRefCountObjectPtr<DataArrayInt> famIds3=fieldFamIds->getDifferentValues();
           std::vector<int> tmp;
-          std::set_intersection(famIds3.begin(),famIds3.end(),famIds2.begin(),famIds2.end(),std::back_insert_iterator< std::vector<int> >(tmp));
+          std::set_intersection(famIds3->begin(),famIds3->end(),famIds2.begin(),famIds2.end(),std::back_insert_iterator< std::vector<int> >(tmp));
           for(std::vector<int>::const_iterator it2=tmp.begin();it2!=tmp.end();it2++)
             {
               ret=false;
               std::string famName=getFamilyNameGivenId(*it2);
               std::ostringstream oss; oss << "Family_" << maxFamId;
               std::string zeName=CreateNameNotIn(oss.str(),allFams);
-              addFamilyOnAllGroupsHaving(famName.c_str(),zeName.c_str());
+              addFamilyOnAllGroupsHaving(famName,zeName);
               _families[zeName]=maxFamId;
               (const_cast<DataArrayInt *>(fieldFamIds))->changeValue(*it2,maxFamId);
               maxFamId++;
@@ -714,12 +1099,14 @@ bool MEDFileMesh::keepFamIdsOnlyOnLevs(const std::vector<int>& famIds, const std
 }
 
 /*!
- * This method add into the family list of a group 'grpName' the family with name 'famName'.
- * If the group 'grpName' does not exist it is created and 'famName' is added to the list.
- * If the group 'grpName' already exists, 'famName' will be added into family list of the existing group.
- * This method throws an INTERP_KERNEL::Exception if 'famName' does not exit.
+ * Adds a family to a given group in \a this mesh. If the group with a given name does
+ * not exist, it is created.
+ *  \param [in] grpName - the name of the group to add the family in.
+ *  \param [in] famName - the name of the family to add to the group named \a grpName.
+ *  \throw If \a grpName or \a famName is an empty string.
+ *  \throw If no family named \a famName is present in \a this mesh.
  */
-void MEDFileMesh::addFamilyOnGrp(const char *grpName, const char *famName) throw(INTERP_KERNEL::Exception)
+void MEDFileMesh::addFamilyOnGrp(const std::string& grpName, const std::string& famName)
 {
   std::string grpn(grpName);
   std::string famn(famName);
@@ -751,7 +1138,7 @@ void MEDFileMesh::addFamilyOnGrp(const char *grpName, const char *famName) throw
  * This method is quite underground because it can lead to unconsistency because family 'otherFamName' is \b not added into _families.
  * This method is used by MEDFileMesh::keepFamIdsOnlyOnLevs method.
  */
-void MEDFileMesh::addFamilyOnAllGroupsHaving(const char *famName, const char *otherFamName) throw(INTERP_KERNEL::Exception)
+void MEDFileMesh::addFamilyOnAllGroupsHaving(const std::string& famName, const std::string& otherFamName)
 {
   std::string famNameCpp(famName);
   std::string otherCpp(otherFamName);
@@ -765,12 +1152,91 @@ void MEDFileMesh::addFamilyOnAllGroupsHaving(const char *famName, const char *ot
     }
 }
 
-void MEDFileMesh::changeAllGroupsContainingFamily(const char *familyNameToChange, const std::vector<std::string>& newFamiliesNames) throw(INTERP_KERNEL::Exception)
+/*!
+ * \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 MEDFileMesh::addGroupUnderground(bool isNodeGroup, const DataArrayInt *ids, DataArrayInt *famArr)
+{
+  if(!ids)
+    throw INTERP_KERNEL::Exception("MEDFileUMesh::addGroup : NULL pointer in input !");
+  std::string grpName(ids->getName());
+  if(grpName.empty())
+    throw INTERP_KERNEL::Exception("MEDFileUMesh::addGroup : empty group name ! MED file format do not accept empty group name !");
+  ids->checkStrictlyMonotonic(true);
+  famArr->incrRef(); MEDCouplingAutoRefCountObjectPtr<DataArrayInt> famArrTmp(famArr);
+  std::vector<std::string> grpsNames=getGroupsNames();
+  if(std::find(grpsNames.begin(),grpsNames.end(),grpName)!=grpsNames.end())
+    {
+      std::ostringstream oss; oss << "MEDFileUMesh::addGroup : Group with name \"" << grpName << "\" already exists ! Destroy it before calling this method !";
+      throw INTERP_KERNEL::Exception(oss.str().c_str());
+    }
+  std::list< MEDCouplingAutoRefCountObjectPtr<DataArrayInt> > allFamIds(getAllNonNullFamilyIds());
+  allFamIds.erase(std::find(allFamIds.begin(),allFamIds.end(),famArrTmp));
+  MEDCouplingAutoRefCountObjectPtr<DataArrayInt> famIds=famArr->selectByTupleIdSafe(ids->begin(),ids->end());
+  MEDCouplingAutoRefCountObjectPtr<DataArrayInt> diffFamIds=famIds->getDifferentValues();
+  std::vector<int> familyIds;
+  std::vector< MEDCouplingAutoRefCountObjectPtr<DataArrayInt> > idsPerfamiliyIds;
+  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;
+  bool created(false);
+  for(const int *famId=diffFamIds->begin();famId!=diffFamIds->end();famId++)
+    {
+      MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ids2Tmp=famIds->getIdsEqual(*famId);
+      MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ids2=ids->selectByTupleId(ids2Tmp->begin(),ids2Tmp->end());
+      MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ids1=famArr->getIdsEqual(*famId);
+      MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret0(ids1->buildSubstractionOptimized(ids2));
+      if(ret0->empty())
+        {
+          bool isFamPresent=false;
+          for(std::list< MEDCouplingAutoRefCountObjectPtr<DataArrayInt> >::const_iterator itl=allFamIds.begin();itl!=allFamIds.end() && !isFamPresent;itl++)
+            isFamPresent=(*itl)->presenceOfValue(*famId);
+          if(!isFamPresent)
+            { familyIds.push_back(*famId); idsPerfamiliyIds.push_back(ret0); fams.push_back(FindOrCreateAndGiveFamilyWithId(families,*famId,created)); } // adding *famId in grp
+          else
+            {
+              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))
+                {
+                  std::string locFamName2=getFamilyNameGivenId(*famId); std::vector<std::string> v(2); v[0]=locFamName2; v[1]=locFamName;
+                  ChangeAllGroupsContainingFamily(groups,getFamilyNameGivenId(*famId),v);
+                }
+              maxVal++;
+            } // modifying all other groups on *famId to lie on maxVal and lie the grp on maxVal
+        }
+      else
+        {
+          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,isNodeGroup?maxVal:-maxVal,created)); std::vector<std::string> v(2); v[0]=n1; v[1]=n2;
+              ChangeAllGroupsContainingFamily(groups,getFamilyNameGivenId(*famId),v);
+            }
+          maxVal+=2;
+        }
+    }
+  for(std::size_t i=0;i<familyIds.size();i++)
+    {
+      DataArrayInt *da=idsPerfamiliyIds[i];
+      famArr->setPartOfValuesSimple3(familyIds[i],da->begin(),da->end(),0,1,1);
+    }
+  _families=families;
+  _groups=groups;
+  _groups[grpName]=fams;
+}
+
+void MEDFileMesh::changeAllGroupsContainingFamily(const std::string& familyNameToChange, const std::vector<std::string>& newFamiliesNames)
 {
   ChangeAllGroupsContainingFamily(_groups,familyNameToChange,newFamiliesNames);
 }
 
-void MEDFileMesh::ChangeAllGroupsContainingFamily(std::map<std::string, std::vector<std::string> >& groups, const char *familyNameToChange, const std::vector<std::string>& newFamiliesNames) throw(INTERP_KERNEL::Exception)
+void MEDFileMesh::ChangeAllGroupsContainingFamily(std::map<std::string, std::vector<std::string> >& groups, const std::string& familyNameToChange, const std::vector<std::string>& newFamiliesNames)
 {
   std::string fam(familyNameToChange);
   for(std::map<std::string, std::vector<std::string> >::iterator it=groups.begin();it!=groups.end();it++)
@@ -786,14 +1252,14 @@ void MEDFileMesh::ChangeAllGroupsContainingFamily(std::map<std::string, std::vec
 }
 
 /*!
- * If it exists a family whose family id is equal to 'id' this method behaves as MEDFileMesh::getFamilyNameGivenId.
- * In this case, 'this' internal states remains unchanged and 'created' out parameter will be set to false.
- * If there is no family whose family id is equal to 'id' a family is created with a name different from those
- * already existing. In this case 'created' will be returned with a value set to true, and internal state
- * will be modified.
- * This method will throws an exception if it is not possible to create a unique family name.
+ * Returns a name of the family having a given id or, if no such a family exists, creates
+ * a new uniquely named family and returns its name.
+ *  \param [in] id - the id of the family whose name is required.
+ *  \param [out] created - returns \c true if the new family has been created, \c false, else.
+ *  \return std::string - the name of the existing or the created family.
+ *  \throw If it is not possible to create a unique family name.
  */
-std::string MEDFileMesh::findOrCreateAndGiveFamilyWithId(int id, bool& created) throw(INTERP_KERNEL::Exception)
+std::string MEDFileMesh::findOrCreateAndGiveFamilyWithId(int id, bool& created)
 {
   return FindOrCreateAndGiveFamilyWithId(_families,id,created);
 }
@@ -806,7 +1272,7 @@ std::string MEDFileMesh::findOrCreateAndGiveFamilyWithId(int id, bool& created)
  * will be modified.
  * This method will throws an exception if it is not possible to create a unique family name.
  */
-std::string MEDFileMesh::FindOrCreateAndGiveFamilyWithId(std::map<std::string,int>& families, int id, bool& created) throw(INTERP_KERNEL::Exception)
+std::string MEDFileMesh::FindOrCreateAndGiveFamilyWithId(std::map<std::string,int>& families, int id, bool& created)
 {
   std::vector<std::string> famAlreadyExisting(families.size());
   int ii=0;
@@ -829,17 +1295,32 @@ std::string MEDFileMesh::FindOrCreateAndGiveFamilyWithId(std::map<std::string,in
   return ret;
 }
 
+/*!
+ * Sets names and ids of all families in \a this mesh.
+ *  \param [in] info - a map of a family name to a family id.
+ */
 void MEDFileMesh::setFamilyInfo(const std::map<std::string,int>& info)
 {
   _families=info;
 }
 
+/*!
+ * Sets names of all groups and families constituting them in \a this mesh.
+ *  \param [in] info - a map of a group name to a vector of names of families
+ *          constituting the group.
+ */
 void MEDFileMesh::setGroupInfo(const std::map<std::string, std::vector<std::string> >&info)
 {
   _groups=info;
 }
 
-int MEDFileMesh::getFamilyId(const char *name) const throw(INTERP_KERNEL::Exception)
+/*!
+ * Returns an id of the family having a given name.
+ *  \param [in] name - the name of the family of interest.
+ *  \return int - the id of the family of interest.
+ *  \throw If no family with such a \a name exists.
+ */
+int MEDFileMesh::getFamilyId(const std::string& name) const
 {
   std::string oname(name);
   std::map<std::string, int>::const_iterator it=_families.find(oname);
@@ -853,7 +1334,13 @@ int MEDFileMesh::getFamilyId(const char *name) const throw(INTERP_KERNEL::Except
   return (*it).second;
 }
 
-std::vector<int> MEDFileMesh::getFamiliesIds(const std::vector<std::string>& fams) const throw(INTERP_KERNEL::Exception)
+/*!
+ * Returns ids of the families having given names.
+ *  \param [in] fams - a sequence of the names of families of interest.
+ *  \return std::vector<int> - a sequence of the ids of families of interest.
+ *  \throw If \a fams contains a name of an inexistent family.
+ */
+std::vector<int> MEDFileMesh::getFamiliesIds(const std::vector<std::string>& fams) const
 {
   std::vector<int> ret(fams.size());
   int i=0;
@@ -872,40 +1359,91 @@ std::vector<int> MEDFileMesh::getFamiliesIds(const std::vector<std::string>& fam
   return ret;
 }
 
-int MEDFileMesh::getMaxFamilyId() const throw(INTERP_KERNEL::Exception)
+/*!
+ * 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
 {
   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++)
     {
-      ret=std::max((*it).second,ret);
+      ret=std::max(std::abs((*it).second),ret);
     }
   return ret;
 }
 
-int MEDFileMesh::getMinFamilyId() const throw(INTERP_KERNEL::Exception)
+/*!
+ * Returns a maximal id of families in \a this mesh.
+ *  \return int - the maximal family id.
+ *  \throw If there are no families in \a this mesh.
+ */
+int MEDFileMesh::getMaxFamilyId() const
 {
   if(_families.empty())
-    throw INTERP_KERNEL::Exception("MEDFileUMesh::getMinFamilyId : no families set !");
-  int ret=std::numeric_limits<int>::max();
+    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::min((*it).second,ret);
+      ret=std::max((*it).second,ret);
     }
   return ret;
 }
 
-int MEDFileMesh::getTheMaxFamilyId() const throw(INTERP_KERNEL::Exception)
+/*!
+ * Returns a minimal id of families in \a this mesh.
+ *  \return int - the minimal family id.
+ *  \throw If there are no families in \a this mesh.
+ */
+int MEDFileMesh::getMinFamilyId() const
 {
-  int m1=-std::numeric_limits<int>::max();
-  for(std::map<std::string,int>::const_iterator it=_families.begin();it!=_families.end();it++)
+  if(_families.empty())
+    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++)
+    {
+      ret=std::min((*it).second,ret);
+    }
+  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
+{
+  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.
+ *  \return int - the maximal family id.
+ */
+int MEDFileMesh::getTheMaxFamilyId() const
+{
+  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((*it).second,m1);
   int m2=getMaxFamilyIdInArrays();
   return std::max(m1,m2);
 }
 
-int MEDFileMesh::getTheMinFamilyId() const throw(INTERP_KERNEL::Exception)
+/*!
+ * 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
 {
   int m1=std::numeric_limits<int>::max();
   for(std::map<std::string,int>::const_iterator it=_families.begin();it!=_families.end();it++)
@@ -914,7 +1452,12 @@ int MEDFileMesh::getTheMinFamilyId() const throw(INTERP_KERNEL::Exception)
   return std::min(m1,m2);
 }
 
-DataArrayInt *MEDFileMesh::getAllFamiliesIdsReferenced() const throw(INTERP_KERNEL::Exception)
+/*!
+ * This method only considers the maps. The contain of family array is ignored here.
+ * 
+ * \sa MEDFileMesh::computeAllFamilyIdsInUse
+ */
+DataArrayInt *MEDFileMesh::getAllFamiliesIdsReferenced() const
 {
   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret=DataArrayInt::New();
   std::set<int> v;
@@ -925,11 +1468,32 @@ 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
+{
+  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.       
  */
-bool MEDFileMesh::ensureDifferentFamIdsPerLevel() throw(INTERP_KERNEL::Exception)
+bool MEDFileMesh::ensureDifferentFamIdsPerLevel()
 {
   std::vector<int> levs=getNonEmptyLevelsExt();
   std::set<int> allFamIds;
@@ -940,13 +1504,13 @@ bool MEDFileMesh::ensureDifferentFamIdsPerLevel() throw(INTERP_KERNEL::Exception
       const DataArrayInt *fam=getFamilyFieldAtLevel(*it);
       if(fam)
         {
-          std::set<int> tmp=fam->getDifferentValues();
+          MEDCouplingAutoRefCountObjectPtr<DataArrayInt> tmp=fam->getDifferentValues();
           std::set<int> r2;
-          std::set_intersection(tmp.begin(),tmp.end(),allFamIds.begin(),allFamIds.end(),std::inserter(r2,r2.end()));
+          std::set_intersection(tmp->begin(),tmp->end(),allFamIds.begin(),allFamIds.end(),std::inserter(r2,r2.end()));
           if(!r2.empty())
             famIdsToRenum[*it].insert(famIdsToRenum[*it].end(),r2.begin(),r2.end());
           std::set<int> r3;
-          std::set_union(tmp.begin(),tmp.end(),allFamIds.begin(),allFamIds.end(),std::inserter(r3,r3.end()));
+          std::set_union(tmp->begin(),tmp->end(),allFamIds.begin(),allFamIds.end(),std::inserter(r3,r3.end()));
         }
     }
   if(famIdsToRenum.empty())
@@ -962,12 +1526,12 @@ bool MEDFileMesh::ensureDifferentFamIdsPerLevel() throw(INTERP_KERNEL::Exception
           if(allIds->presenceOfValue(*it3))
             {
               std::string famName=getFamilyNameGivenId(*it3);
-              std::vector<std::string> grps=getGroupsOnFamily(famName.c_str());
+              std::vector<std::string> grps=getGroupsOnFamily(famName);
               ren[*it3]=maxId;
               bool dummy;
               std::string newFam=findOrCreateAndGiveFamilyWithId(maxId,dummy);
               for(std::vector<std::string>::const_iterator it4=grps.begin();it4!=grps.end();it4++)
-                addFamilyOnGrp((*it4).c_str(),newFam.c_str());
+                addFamilyOnGrp((*it4),newFam);
             }
         }
       MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ids=fam->getIdsEqualList(&(*it2).second[0],&(*it2).second[0]+(*it2).second.size());
@@ -984,7 +1548,7 @@ bool MEDFileMesh::ensureDifferentFamIdsPerLevel() throw(INTERP_KERNEL::Exception
  * This method will throw an exception if a same family id is detected in different level.
  * \warning This policy is the opposite of those in MED file documentation ...
  */
-void MEDFileMesh::normalizeFamIdsTrio() throw(INTERP_KERNEL::Exception)
+void MEDFileMesh::normalizeFamIdsTrio()
 {
   ensureDifferentFamIdsPerLevel();
   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> allIds=getAllFamiliesIdsReferenced();
@@ -999,15 +1563,15 @@ void MEDFileMesh::normalizeFamIdsTrio() throw(INTERP_KERNEL::Exception)
       if(fam)
         {
           int refId=1;
-          std::set<int> tmp=fam->getDifferentValues();
+          MEDCouplingAutoRefCountObjectPtr<DataArrayInt> tmp=fam->getDifferentValues();
           std::map<int,int> ren;
-          for(std::set<int>::const_iterator it=tmp.begin();it!=tmp.end();it++,refId++)
+          for(const int *it=tmp->begin();it!=tmp->end();it++,refId++)
             ren[*it]=refId;
           int nbOfTuples=fam->getNumberOfTuples();
           int *start=const_cast<DataArrayInt *>(fam)->getPointer();
           for(int *w=start;w!=start+nbOfTuples;w++)
             *w=ren[*w];
-          for(std::set<int>::const_iterator it=tmp.begin();it!=tmp.end();it++)
+          for(const int *it=tmp->begin();it!=tmp->end();it++)
             {
               if(allIds->presenceOfValue(*it))
                 {
@@ -1025,15 +1589,15 @@ void MEDFileMesh::normalizeFamIdsTrio() throw(INTERP_KERNEL::Exception)
       if(fam)
         {
           int refId=-1;
-          std::set<int> tmp=fam->getDifferentValues();
+          MEDCouplingAutoRefCountObjectPtr<DataArrayInt> tmp=fam->getDifferentValues();
           std::map<int,int> ren;
-          for(std::set<int>::const_iterator it=tmp.begin();it!=tmp.end();it++,refId--)
+          for(const int *it=tmp->begin();it!=tmp->end();it++,refId--)
             ren[*it]=refId;
           int nbOfTuples=fam->getNumberOfTuples();
           int *start=const_cast<DataArrayInt *>(fam)->getPointer();
           for(int *w=start;w!=start+nbOfTuples;w++)
             *w=ren[*w];
-          for(std::set<int>::const_iterator it=tmp.begin();it!=tmp.end();it++)
+          for(const int *it=tmp->begin();it!=tmp->end();it++)
             {
               if(allIds->presenceOfValue(*it))
                 {
@@ -1049,9 +1613,9 @@ void MEDFileMesh::normalizeFamIdsTrio() throw(INTERP_KERNEL::Exception)
       DataArrayInt *fam=const_cast<DataArrayInt*>(getFamilyFieldAtLevel(*it2));
       if(fam)
         {
-          std::set<int> tmp=fam->getDifferentValues();
+          MEDCouplingAutoRefCountObjectPtr<DataArrayInt> tmp=fam->getDifferentValues();
           fam->fillWithZero();
-          for(std::set<int>::const_iterator it3=tmp.begin();it3!=tmp.end();it3++)
+          for(const int *it3=tmp->begin();it3!=tmp->end();it3++)
             if(allIds->presenceOfValue(*it3))
               {
                 std::string famName=getFamilyNameGivenId(*it3);
@@ -1076,7 +1640,7 @@ void MEDFileMesh::normalizeFamIdsTrio() throw(INTERP_KERNEL::Exception)
  * This policy is those defined in the MED file format but is the opposite of those implemented in SMESH and Trio.
  * This method will throw an exception if a same family id is detected in different level.
  */
-void MEDFileMesh::normalizeFamIdsMEDFile() throw(INTERP_KERNEL::Exception)
+void MEDFileMesh::normalizeFamIdsMEDFile()
 {
   ensureDifferentFamIdsPerLevel();
   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> allIds=getAllFamiliesIdsReferenced();
@@ -1091,15 +1655,15 @@ void MEDFileMesh::normalizeFamIdsMEDFile() throw(INTERP_KERNEL::Exception)
       const DataArrayInt *fam=getFamilyFieldAtLevel(1);
       if(fam)
         {
-          std::set<int> tmp=fam->getDifferentValues();
+          MEDCouplingAutoRefCountObjectPtr<DataArrayInt> tmp=fam->getDifferentValues();
           std::map<int,int> ren;
-          for(std::set<int>::const_iterator it=tmp.begin();it!=tmp.end();it++,refId++)
+          for(const int *it=tmp->begin();it!=tmp->end();it++,refId++)
             ren[*it]=refId;
           int nbOfTuples=fam->getNumberOfTuples();
           int *start=const_cast<DataArrayInt *>(fam)->getPointer();
           for(int *w=start;w!=start+nbOfTuples;w++)
             *w=ren[*w];
-          for(std::set<int>::const_iterator it=tmp.begin();it!=tmp.end();it++)
+          for(const int *it=tmp->begin();it!=tmp->end();it++)
             {
               if(allIds->presenceOfValue(*it))
                 {
@@ -1113,18 +1677,18 @@ 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)
         {
-          std::set<int> tmp=fam->getDifferentValues();
+          MEDCouplingAutoRefCountObjectPtr<DataArrayInt> tmp=fam->getDifferentValues();
           std::map<int,int> ren;
-          for(std::set<int>::const_iterator it=tmp.begin();it!=tmp.end();it++,refId--)
+          for(const int *it=tmp->begin();it!=tmp->end();it++,refId--)
             ren[*it]=refId;
           int nbOfTuples=fam->getNumberOfTuples();
           int *start=const_cast<DataArrayInt *>(fam)->getPointer();
           for(int *w=start;w!=start+nbOfTuples;w++)
             *w=ren[*w];
-          for(std::set<int>::const_iterator it=tmp.begin();it!=tmp.end();it++)
+          for(const int *it=tmp->begin();it!=tmp->end();it++)
             {
               if(allIds->presenceOfValue(*it))
                 {
@@ -1146,9 +1710,13 @@ void MEDFileMesh::normalizeFamIdsMEDFile() throw(INTERP_KERNEL::Exception)
 }
 
 /*!
- * Returns the first (in lexical order) family name having family id equal to 'id'.
+ * Returns a name of the family by its id. If there are several families having the given
+ * id, the name first in lexical order is returned.
+ *  \param [in] id - the id of the family whose name is required.
+ *  \return std::string - the name of the found family.
+ *  \throw If no family with the given \a id exists.
  */
-std::string MEDFileMesh::getFamilyNameGivenId(int id) const throw(INTERP_KERNEL::Exception)
+std::string MEDFileMesh::getFamilyNameGivenId(int id) const
 {
   for(std::map<std::string,int>::const_iterator it=_families.begin();it!=_families.end();it++)
     if((*it).second==id)
@@ -1157,6 +1725,11 @@ std::string MEDFileMesh::getFamilyNameGivenId(int id) const throw(INTERP_KERNEL:
   throw INTERP_KERNEL::Exception(oss.str().c_str());
 }
 
+/*!
+ * Returns a string describing \a this mesh. This description includes the mesh name and
+ * the mesh description string.
+ *  \return std::string - the mesh information string.
+ */
 std::string MEDFileMesh::simpleRepr() const
 {
   std::ostringstream oss;
@@ -1166,7 +1739,36 @@ std::string MEDFileMesh::simpleRepr() const
   return oss.str();
 }
 
-DataArrayInt *MEDFileMesh::getGroupArr(int meshDimRelToMaxExt, const char *grp, bool renum) const throw(INTERP_KERNEL::Exception)
+/*!
+ * This method is nearly like getFamilyFieldAtLevel method. Except that if the array does not exist at the specified level \a meshDimRelToMaxExt
+ * an empty one is created.
+ */
+DataArrayInt *MEDFileMesh::getOrCreateAndGetFamilyFieldAtLevel(int meshDimRelToMaxExt)
+{
+  DataArrayInt *ret(getFamilyFieldAtLevel(meshDimRelToMaxExt));
+  if(ret)
+    return ret;
+  MEDCouplingAutoRefCountObjectPtr<DataArrayInt> arr(DataArrayInt::New());
+  arr->alloc(getSizeAtLevel(meshDimRelToMaxExt),1);
+  arr->fillWithZero();
+  setFamilyFieldArr(meshDimRelToMaxExt,arr);
+  return getFamilyFieldAtLevel(meshDimRelToMaxExt);
+}
+
+/*!
+ * Returns ids of mesh entities contained in a given group of a given dimension.
+ *  \param [in] meshDimRelToMaxExt - a relative dimension of the mesh entities whose ids
+ *          are required.
+ *  \param [in] grp - the name of the group of interest.
+ *  \param [in] renum - if \c true, the optional numbers of entities, if available, are
+ *          returned instead of ids. 
+ *  \return DataArrayInt * - a new instance of DataArrayInt holding either ids or
+ *          numbers, if available and required, of mesh entities of the group. The caller
+ *          is to delete this array using decrRef() as it is no more needed. 
+ *  \throw If the name of a nonexistent group is specified.
+ *  \throw If the family field is missing for \a meshDimRelToMaxExt.
+ */
+DataArrayInt *MEDFileMesh::getGroupArr(int meshDimRelToMaxExt, const std::string& grp, bool renum) const
 {
   std::vector<std::string> tmp(1);
   tmp[0]=grp;
@@ -1175,13 +1777,38 @@ DataArrayInt *MEDFileMesh::getGroupArr(int meshDimRelToMaxExt, const char *grp,
   return ret;
 }
 
-DataArrayInt *MEDFileMesh::getGroupsArr(int meshDimRelToMaxExt, const std::vector<std::string>& grps, bool renum) const throw(INTERP_KERNEL::Exception)
+/*!
+ * Returns ids of mesh entities contained in given groups of a given dimension.
+ *  \param [in] meshDimRelToMaxExt - a relative dimension of the mesh entities whose ids
+ *          are required.
+ *  \param [in] grps - the names of the groups of interest.
+ *  \param [in] renum - if \c true, the optional numbers of entities, if available, are
+ *          returned instead of ids.
+ *  \return DataArrayInt * - a new instance of DataArrayInt holding either ids or
+ *          numbers, if available and required, of mesh entities of the groups. The caller
+ *          is to delete this array using decrRef() as it is no more needed. 
+ *  \throw If the name of a nonexistent group is present in \a grps.
+ *  \throw If the family field is missing for \a meshDimRelToMaxExt.
+ */
+DataArrayInt *MEDFileMesh::getGroupsArr(int meshDimRelToMaxExt, const std::vector<std::string>& grps, bool renum) const
 {
   std::vector<std::string> fams2=getFamiliesOnGroups(grps);
   return getFamiliesArr(meshDimRelToMaxExt,fams2,renum);
 }
 
-DataArrayInt *MEDFileMesh::getFamilyArr(int meshDimRelToMaxExt, const char *fam, bool renum) const throw(INTERP_KERNEL::Exception)
+/*!
+ * Returns ids of mesh entities contained in a given family of a given dimension.
+ *  \param [in] meshDimRelToMaxExt - a relative dimension of the mesh entities whose ids
+ *          are required.
+ *  \param [in] fam - the name of the family of interest.
+ *  \param [in] renum - if \c true, the optional numbers of entities, if available, are
+ *          returned instead of ids. 
+ *  \return DataArrayInt * - a new instance of DataArrayInt holding either ids or
+ *          numbers, if available and required, of mesh entities of the family. The caller
+ *          is to delete this array using decrRef() as it is no more needed. 
+ *  \throw If the family field is missing for \a meshDimRelToMaxExt.
+ */
+DataArrayInt *MEDFileMesh::getFamilyArr(int meshDimRelToMaxExt, const std::string& fam, bool renum) const
 {
   std::vector<std::string> tmp(1);
   tmp[0]=fam;
@@ -1190,7 +1817,18 @@ DataArrayInt *MEDFileMesh::getFamilyArr(int meshDimRelToMaxExt, const char *fam,
   return ret;
 }
 
-DataArrayInt *MEDFileMesh::getNodeGroupArr(const char *grp, bool renum) const throw(INTERP_KERNEL::Exception)
+/*!
+ * Returns ids of nodes contained in a given group.
+ *  \param [in] grp - the name of the group of interest.
+ *  \param [in] renum - if \c true, the optional numbers of nodes, if available, are
+ *          returned instead of ids. 
+ *  \return DataArrayInt * - a new instance of DataArrayInt holding either ids or
+ *          numbers, if available and required, of nodes of the group. The caller
+ *          is to delete this array using decrRef() as it is no more needed. 
+ *  \throw If the name of a nonexistent group is specified.
+ *  \throw If the family field is missing for nodes.
+ */
+DataArrayInt *MEDFileMesh::getNodeGroupArr(const std::string& grp, bool renum) const
 {
   std::vector<std::string> tmp(1);
   tmp[0]=grp;
@@ -1199,12 +1837,34 @@ DataArrayInt *MEDFileMesh::getNodeGroupArr(const char *grp, bool renum) const th
   return ret;
 }
 
-DataArrayInt *MEDFileMesh::getNodeGroupsArr(const std::vector<std::string>& grps, bool renum) const throw(INTERP_KERNEL::Exception)
+/*!
+ * Returns ids of nodes contained in given groups.
+ *  \param [in] grps - the names of the groups of interest.
+ *  \param [in] renum - if \c true, the optional numbers of nodes, if available, are
+ *          returned instead of ids. 
+ *  \return DataArrayInt * - a new instance of DataArrayInt holding either ids or
+ *          numbers, if available and required, of nodes of the groups. The caller
+ *          is to delete this array using decrRef() as it is no more needed. 
+ *  \throw If the name of a nonexistent group is present in \a grps.
+ *  \throw If the family field is missing for nodes.
+ */
+DataArrayInt *MEDFileMesh::getNodeGroupsArr(const std::vector<std::string>& grps, bool renum) const
 {
   return getGroupsArr(1,grps,renum);
 }
 
-DataArrayInt *MEDFileMesh::getNodeFamilyArr(const char *fam, bool renum) const throw(INTERP_KERNEL::Exception)
+/*!
+ * Returns ids of nodes contained in a given group.
+ *  \param [in] grp - the name of the group of interest.
+ *  \param [in] renum - if \c true, the optional numbers of nodes, if available, are
+ *          returned instead of ids. 
+ *  \return DataArrayInt * - a new instance of DataArrayInt holding either ids or
+ *          numbers, if available and required, of nodes of the group. The caller
+ *          is to delete this array using decrRef() as it is no more needed. 
+ *  \throw If the name of a nonexistent group is specified.
+ *  \throw If the family field is missing for nodes.
+ */
+DataArrayInt *MEDFileMesh::getNodeFamilyArr(const std::string& fam, bool renum) const
 {
   std::vector<std::string> tmp(1);
   tmp[0]=fam;
@@ -1213,12 +1873,34 @@ DataArrayInt *MEDFileMesh::getNodeFamilyArr(const char *fam, bool renum) const t
   return ret;
 }
 
-DataArrayInt *MEDFileMesh::getNodeFamiliesArr(const std::vector<std::string>& fams, bool renum) const throw(INTERP_KERNEL::Exception)
+/*!
+ * Returns ids of nodes contained in given families.
+ *  \param [in] fams - the names of the families of interest.
+ *  \param [in] renum - if \c true, the optional numbers of nodes, if available, are
+ *          returned instead of ids. 
+ *  \return DataArrayInt * - a new instance of DataArrayInt holding either ids or
+ *          numbers, if available and required, of nodes of the families. The caller
+ *          is to delete this array using decrRef() as it is no more needed. 
+ *  \throw If the family field is missing for nodes.
+ */
+DataArrayInt *MEDFileMesh::getNodeFamiliesArr(const std::vector<std::string>& fams, bool renum) const
 {
   return getFamiliesArr(1,fams,renum);
 }
 
-void MEDFileMesh::setGroupsAtLevel(int meshDimRelToMaxExt, const std::vector<const DataArrayInt *>& grps, bool renum) throw(INTERP_KERNEL::Exception)
+/*!
+ * Adds groups of given dimension and creates corresponding families and family fields
+ * given ids of mesh entities of each group.
+ *  \param [in] meshDimRelToMaxExt - the relative mesh dimension of given mesh entities.
+ *  \param [in] grps - a sequence of arrays of ids each describing a group.
+ *  \param [in] renum - \c true means that \a grps contains not ids but optional numbers
+ *          of mesh entities.
+ *  \throw If names of some groups in \a grps are equal.
+ *  \throw If \a grps includes a group with an empty name.
+ *  \throw If \a grps includes invalid ids (or numbers if \a renum == \c true ).
+ *  \throw If there are no mesh entities of \a meshDimRelToMaxExt dimension in \a this mesh.
+ */
+void MEDFileMesh::setGroupsAtLevel(int meshDimRelToMaxExt, const std::vector<const DataArrayInt *>& grps, bool renum)
 {
   if(grps.empty())
     return ;
@@ -1248,16 +1930,16 @@ void MEDFileMesh::setGroupsAtLevel(int meshDimRelToMaxExt, const std::vector<con
       for(unsigned int ii=0;ii<grps.size();ii++)
         {
           grps2[ii]=MEDFileUMeshSplitL1::Renumber(getRevNumberFieldAtLevel(meshDimRelToMaxExt),grps[ii]);
-          grps2[ii]->setName(grps[ii]->getName().c_str());
+          grps2[ii]->setName(grps[ii]->getName());
         }
       std::vector<const DataArrayInt *> grps3(grps2.begin(),grps2.end());
       fam=DataArrayInt::MakePartition(grps3,sz,fidsOfGroups);
     }
   int offset=1;
   if(!_families.empty())
-    offset=getMaxFamilyId()+1;
-  TranslateFamilyIds(offset,fam,fidsOfGroups);
-  std::set<int> ids=fam->getDifferentValues();
+    offset=getMaxAbsFamilyId()+1;
+  TranslateFamilyIds(meshDimRelToMaxExt==1?offset:-offset,fam,fidsOfGroups);
+  MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ids=fam->getDifferentValues();
   appendFamilyEntries(ids,fidsOfGroups,grpsName2);
   setFamilyFieldArr(meshDimRelToMaxExt,fam);
 }
@@ -1267,10 +1949,10 @@ void MEDFileMesh::setGroupsAtLevel(int meshDimRelToMaxExt, const std::vector<con
  * not in '_families'. Groups information are given in parameters in order to give to families representative names.
  * For the moment, the two last input parameters are not taken into account.
  */
-void MEDFileMesh::appendFamilyEntries(const std::set<int>& famIds, const std::vector< std::vector<int> >& fidsOfGrps, const std::vector<std::string>& grpNames)
+void MEDFileMesh::appendFamilyEntries(const DataArrayInt *famIds, const std::vector< std::vector<int> >& fidsOfGrps, const std::vector<std::string>& grpNames)
 {
   std::map<int,std::string> famInv;
-  for(std::set<int>::const_iterator it=famIds.begin();it!=famIds.end();it++)
+  for(const int *it=famIds->begin();it!=famIds->end();it++)
     {
       std::ostringstream oss;
       oss << "Family_" << (*it);
@@ -1287,11 +1969,33 @@ void MEDFileMesh::appendFamilyEntries(const std::set<int>& famIds, const std::ve
     }
 }
 
+std::vector<INTERP_KERNEL::NormalizedCellType> MEDFileMesh::getAllGeoTypes() const
+{
+  std::vector<int> levs(getNonEmptyLevels());
+  std::vector<INTERP_KERNEL::NormalizedCellType> ret;
+  for(std::vector<int>::const_iterator it=levs.begin();it!=levs.end();it++)
+    {
+      std::vector<INTERP_KERNEL::NormalizedCellType> elts(getGeoTypesAtLevel(*it));
+      ret.insert(ret.end(),elts.begin(),elts.end());
+    }
+  return ret;
+}
+
+std::vector<int> MEDFileMesh::getDistributionOfTypes(int meshDimRelToMax) const
+{
+  MEDCouplingAutoRefCountObjectPtr<MEDCouplingMesh> mLev(getGenMeshAtLevel(meshDimRelToMax));
+  return mLev->getDistributionOfTypes();
+}
+
 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));
+    }
 }
 
 /*!
@@ -1299,7 +2003,7 @@ void MEDFileMesh::TranslateFamilyIds(int offset, DataArrayInt *famArr, std::vect
  * This method returns a name close to 'nameTry' so that it is not already into 'namesToAvoid'.
  * If this method fails to find such a name it will throw an exception.
  */
-std::string MEDFileMesh::CreateNameNotIn(const std::string& nameTry, const std::vector<std::string>& namesToAvoid) throw(INTERP_KERNEL::Exception)
+std::string MEDFileMesh::CreateNameNotIn(const std::string& nameTry, const std::vector<std::string>& namesToAvoid)
 {
   //attempt #0
   if(std::find(namesToAvoid.begin(),namesToAvoid.end(),nameTry)==namesToAvoid.end())
@@ -1332,7 +2036,7 @@ std::string MEDFileMesh::CreateNameNotIn(const std::string& nameTry, const std::
   throw INTERP_KERNEL::Exception("MEDFileMesh::CreateNameNotIn : impossible to find a not already used name !");
 }
 
-int MEDFileMesh::PutInThirdComponentOfCodeOffset(std::vector<int>& code, int strt) throw(INTERP_KERNEL::Exception)
+int MEDFileMesh::PutInThirdComponentOfCodeOffset(std::vector<int>& code, int strt)
 {
   std::size_t nbOfChunks=code.size()/3;
   if(code.size()%3!=0)
@@ -1352,8 +2056,10 @@ int MEDFileMesh::PutInThirdComponentOfCodeOffset(std::vector<int>& code, int str
  * If _name is not empty and that 'm' has the same name nothing is done.
  * If _name is not emplt and that 'm' has \b NOT the same name an exception is thrown.
  */
-void MEDFileMesh::dealWithTinyInfo(const MEDCouplingMesh *m) throw(INTERP_KERNEL::Exception)
+void MEDFileMesh::dealWithTinyInfo(const MEDCouplingMesh *m)
 {
+  if(!m)
+    throw INTERP_KERNEL::Exception("MEDFileMesh::dealWithTinyInfo : input mesh in NULL !");
   if(_name.empty())
     _name=m->getName();
   else
@@ -1393,20 +2099,44 @@ void MEDFileMesh::getFamilyRepr(std::ostream& oss) const
     {
       oss << "- Family with name \"" << (*it).first << "\" with number " << (*it).second << std::endl;
       oss << "  - Groups lying on this family : ";
-      std::vector<std::string> grps=getGroupsOnFamily((*it).first.c_str());
+      std::vector<std::string> grps=getGroupsOnFamily((*it).first);
       std::copy(grps.begin(),grps.end(),std::ostream_iterator<std::string>(oss," "));
       oss << std::endl << std::endl;
     }
 }
 
-MEDFileUMesh *MEDFileUMesh::New(const char *fileName, const char *mName, int dt, int it) throw(INTERP_KERNEL::Exception)
+/*!
+ * Returns a new MEDFileUMesh holding the mesh data that has been read from a given MED
+ * file. The mesh to load is specified by its name and numbers of a time step and an
+ * iteration.
+ *  \param [in] fileName - the name of MED file to read.
+ *  \param [in] mName - the name of the mesh to read.
+ *  \param [in] dt - the number of a time step.
+ *  \param [in] it - the number of an iteration.
+ *  \return MEDFileUMesh * - a new instance of MEDFileUMesh. The caller is to delete this
+ *          mesh using decrRef() as it is no more needed. 
+ *  \throw If the file is not readable.
+ *  \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 std::string& fileName, const std::string& mName, int dt, int it, MEDFileMeshReadSelector *mrs)
 {
   MEDFileUtilities::CheckFileForRead(fileName);
-  MEDFileUtilities::AutoFid fid=MEDfileOpen(fileName,MED_ACC_RDONLY);
-  return new MEDFileUMesh(fid,mName,dt,it);
+  MEDFileUtilities::AutoFid fid=MEDfileOpen(fileName.c_str(),MED_ACC_RDONLY);
+  return new MEDFileUMesh(fid,mName,dt,it,mrs);
 }
 
-MEDFileUMesh *MEDFileUMesh::New(const char *fileName) throw(INTERP_KERNEL::Exception)
+/*!
+ * Returns a new MEDFileUMesh holding the mesh data that has been read from a given MED
+ * file. The first mesh in the file is loaded.
+ *  \param [in] fileName - the name of MED file to read.
+ *  \return MEDFileUMesh * - a new instance of MEDFileUMesh. The caller is to delete this
+ *          mesh using decrRef() as it is no more needed. 
+ *  \throw If the file is not readable.
+ *  \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 std::string& fileName, MEDFileMeshReadSelector *mrs)
 {
   std::vector<std::string> ms=MEDLoader::GetMeshNames(fileName);
   if(ms.empty())
@@ -1415,44 +2145,91 @@ MEDFileUMesh *MEDFileUMesh::New(const char *fileName) throw(INTERP_KERNEL::Excep
       throw INTERP_KERNEL::Exception(oss.str().c_str());
     }
   MEDFileUtilities::CheckFileForRead(fileName);
-  MEDFileUtilities::AutoFid fid=MEDfileOpen(fileName,MED_ACC_RDONLY);
+  MEDFileUtilities::AutoFid fid=MEDfileOpen(fileName.c_str(),MED_ACC_RDONLY);
   int dt,it;
   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);
+  MEDFileMeshL2::GetMeshIdFromName(fid,ms.front(),meshType,dt,it,dummy2);
+  return new MEDFileUMesh(fid,ms.front(),dt,it,mrs);
 }
 
+/*!
+ * Returns an empty instance of MEDFileUMesh.
+ *  \return MEDFileUMesh * - a new instance of MEDFileUMesh. The caller is to delete this
+ *          mesh using decrRef() as it is no more needed. 
+ */
 MEDFileUMesh *MEDFileUMesh::New()
 {
   return new MEDFileUMesh;
 }
 
-std::size_t MEDFileUMesh::getHeapMemorySize() const
+/*!
+ * This method loads from file with name \a fileName the mesh called \a mName as New does. The difference is that
+ * here only a part of cells contained in the file will be loaded. The selection of cell is specified using the two consecutive parameters
+ * \a types and \a slicPerTyp. This method allows to load from a mesh (typically huge) in a MED file a part of cells of that mesh.
+ * The part of cells is specified using triplet (start,stop,step) for each geometric type. Only nodes lying on selected cells will be loaded to reduce
+ * at most the memory consumtion.
+ *
+ * \param [in] fileName - the name of the file.
+ * \param [in] mName - the name of the mesh to be read.
+ * \param [in] types - the list of the geo types of which some part will be taken. A geometric type in \a types must appear only once at most.
+ * \param [in] slicPerType - an array of size 3 times larger than \a types that specifies for each type in \a types (in the same order) resp the start, the stop and the step.
+ * \param [in] dt - the iteration, that is to say the first element of the pair that locates the asked time step.
+ * \param [in] it - the order, that is to say the second element of the pair that locates the asked time step.
+ * \param [in] mrs - the request for what to be loaded.
+ * \return MEDFileUMesh * - a new instance of MEDFileUMesh. The caller is to delete this mesh using decrRef() as it is no more needed.
+ */
+MEDFileUMesh *MEDFileUMesh::LoadPartOf(const std::string& fileName, const std::string& mName, const std::vector<INTERP_KERNEL::NormalizedCellType>& types, const std::vector<int>& slicPerTyp, int dt, int it, MEDFileMeshReadSelector *mrs)
 {
-  std::size_t ret=MEDFileMesh::getHeapMemorySize();
-  if((const DataArrayDouble*)_coords)
-    ret+=_coords->getHeapMemorySize();
-  if((const DataArrayInt *)_fam_coords)
-    ret+=_fam_coords->getHeapMemorySize();
-  if((const DataArrayInt *)_num_coords)
-    ret+=_num_coords->getHeapMemorySize();
-  if((const DataArrayInt *)_rev_num_coords)
-    ret+=_rev_num_coords->getHeapMemorySize();
+  MEDFileUtilities::CheckFileForRead(fileName);
+  MEDFileUtilities::AutoFid fid(MEDfileOpen(fileName.c_str(),MED_ACC_RDONLY));
+  return MEDFileUMesh::LoadPartOf(fid,mName,types,slicPerTyp,dt,it,mrs);
+}
+
+/*!
+ * Please refer to the other MEDFileUMesh::LoadPartOf method that has the same semantic and the same parameter (excepted the first).
+ * This method is \b NOT wrapped into python.
+ */
+MEDFileUMesh *MEDFileUMesh::LoadPartOf(med_idt fid, const std::string& mName, const std::vector<INTERP_KERNEL::NormalizedCellType>& types, const std::vector<int>& slicPerTyp, int dt, int it, MEDFileMeshReadSelector *mrs)
+{
+  MEDCouplingAutoRefCountObjectPtr<MEDFileUMesh> ret(MEDFileUMesh::New());
+  ret->loadPartUMeshFromFile(fid,mName,types,slicPerTyp,dt,it,mrs);
+  return ret.retn();
+}
+
+std::size_t MEDFileUMesh::getHeapMemorySizeWithoutChildren() const
+{
+  std::size_t ret(MEDFileMesh::getHeapMemorySizeWithoutChildren());
   ret+=_ms.capacity()*(sizeof(MEDCouplingAutoRefCountObjectPtr<MEDFileUMeshSplitL1>));
+  return ret;
+}
+
+std::vector<const BigMemoryObject *> MEDFileUMesh::getDirectChildrenWithNull() const
+{
+  std::vector<const BigMemoryObject *> ret(MEDFileMesh::getDirectChildrenWithNull());
+  ret.push_back((const DataArrayDouble*)_coords);
+  ret.push_back((const DataArrayInt *)_fam_coords);
+  ret.push_back((const DataArrayInt *)_num_coords);
+  ret.push_back((const DataArrayInt *)_rev_num_coords);
+  ret.push_back((const DataArrayAsciiChar *)_name_coords);
+  ret.push_back((const PartDefinition *)_part_coords);
   for(std::vector< MEDCouplingAutoRefCountObjectPtr<MEDFileUMeshSplitL1> >::const_iterator it=_ms.begin();it!=_ms.end();it++)
-    if((const MEDFileUMeshSplitL1*) *it)
-      ret+=(*it)->getHeapMemorySize();
+    ret.push_back((const MEDFileUMeshSplitL1*) *it);
   return ret;
 }
 
-MEDFileMesh *MEDFileUMesh::shallowCpy() const throw(INTERP_KERNEL::Exception)
+MEDFileMesh *MEDFileUMesh::shallowCpy() const
 {
   MEDCouplingAutoRefCountObjectPtr<MEDFileUMesh> ret=new MEDFileUMesh(*this);
   return ret.retn();
 }
 
-MEDFileMesh *MEDFileUMesh::deepCpy() const throw(INTERP_KERNEL::Exception)
+MEDFileMesh *MEDFileUMesh::createNewEmpty() const
+{
+  return new MEDFileUMesh;
+}
+
+MEDFileMesh *MEDFileUMesh::deepCpy() const
 {
   MEDCouplingAutoRefCountObjectPtr<MEDFileUMesh> ret=new MEDFileUMesh(*this);
   if((const DataArrayDouble*)_coords)
@@ -1463,15 +2240,26 @@ MEDFileMesh *MEDFileUMesh::deepCpy() const throw(INTERP_KERNEL::Exception)
     ret->_num_coords=_num_coords->deepCpy();
   if((const DataArrayInt*)_rev_num_coords)
     ret->_rev_num_coords=_rev_num_coords->deepCpy();
+  if((const DataArrayAsciiChar*)_name_coords)
+    ret->_name_coords=_name_coords->deepCpy();
   std::size_t i=0;
   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);
     }
+  if((const PartDefinition*)_part_coords)
+    ret->_part_coords=_part_coords->deepCpy();
   return ret.retn();
 }
 
+/*!
+ * Checks if \a this and another mesh are equal.
+ *  \param [in] other - the mesh to compare with.
+ *  \param [in] eps - a precision used to compare real values.
+ *  \param [in,out] what - the string returning description of unequal data.
+ *  \return bool - \c true if the meshes are equal, \c false, else.
+ */
 bool MEDFileUMesh::isEqual(const MEDFileMesh *other, double eps, std::string& what) const
 {
   if(!MEDFileMesh::isEqual(other,eps,what))
@@ -1532,6 +2320,22 @@ bool MEDFileUMesh::isEqual(const MEDFileMesh *other, double eps, std::string& wh
           return false;
         }
     }
+  const DataArrayAsciiChar *namec1=_name_coords;
+  const DataArrayAsciiChar *namec2=otherC->_name_coords;
+  if((namec1==0 && namec2!=0) || (namec1!=0 && namec2==0))
+    {
+      what="Mismatch of naming arr on nodes ! One is defined and not other !";
+      return false;
+    }
+  if(namec1)
+    {
+      bool ret=namec1->isEqual(*namec2);
+      if(!ret)
+        {
+          what="Names arr on node differ !";
+          return false;
+        }
+    }
   if(_ms.size()!=otherC->_ms.size())
     {
       what="Number of levels differs !";
@@ -1554,9 +2358,20 @@ bool MEDFileUMesh::isEqual(const MEDFileMesh *other, double eps, std::string& wh
             return false;
         }
     }
-  return true;
+  const PartDefinition *pd0(_part_coords),*pd1(otherC->_part_coords);
+  if(!pd0 && !pd1)
+    return true;
+  if((!pd0 && pd1) || (pd0 && !pd1))
+    {
+      what=std::string("node part def is defined only for one among this or other !");
+      return false;
+    }
+  return pd0->isEqual(pd1,what);
 }
 
+/*!
+ * Clears redundant attributes of incorporated data arrays.
+ */
 void MEDFileUMesh::clearNonDiscrAttributes() const
 {
   MEDFileMesh::clearNonDiscrAttributes();
@@ -1569,6 +2384,9 @@ void MEDFileUMesh::clearNonDiscrAttributes() const
   const DataArrayInt *numc1=_num_coords;
   if(numc1)
     (const_cast<DataArrayInt *>(numc1))->setName("");//This parameter is not discriminant for comparison
+  const DataArrayAsciiChar *namc1=_name_coords;
+  if(namc1)
+    (const_cast<DataArrayAsciiChar *>(namc1))->setName("");//This parameter is not discriminant for comparison
   for(std::vector< MEDCouplingAutoRefCountObjectPtr<MEDFileUMeshSplitL1> >::const_iterator it=_ms.begin();it!=_ms.end();it++)
     {
       const MEDFileUMeshSplitL1 *tmp=(*it);
@@ -1577,33 +2395,130 @@ void MEDFileUMesh::clearNonDiscrAttributes() const
     }
 }
 
+void MEDFileUMesh::setName(const std::string& name)
+{
+  for(std::vector< MEDCouplingAutoRefCountObjectPtr<MEDFileUMeshSplitL1> >::iterator it=_ms.begin();it!=_ms.end();it++)
+    if((MEDFileUMeshSplitL1 *)(*it)!=0)
+      (*it)->setName(name);
+  MEDFileMesh::setName(name);
+}
+
 MEDFileUMesh::MEDFileUMesh()
 {
 }
 
-MEDFileUMesh::MEDFileUMesh(med_idt fid, const char *mName, int dt, int it) throw(INTERP_KERNEL::Exception)
+MEDFileUMesh::MEDFileUMesh(med_idt fid, const std::string& mName, int dt, int it, MEDFileMeshReadSelector *mrs)
 try
-  {
-    loadUMeshFromFile(fid,mName,dt,it);
+{
+    loadUMeshFromFile(fid,mName,dt,it,mrs);
+    loadJointsFromFile(fid);
   }
 catch(INTERP_KERNEL::Exception& e)
-  {
+{
     throw e;
-  }
+}
+
+/*!
+ * This method loads only a part of specified cells (given by range of cell ID per geometric type)
+ * See MEDFileUMesh::LoadPartOf for detailed description.
+ *
+ * \sa loadUMeshFromFile
+ */
+void MEDFileUMesh::loadPartUMeshFromFile(med_idt fid, const std::string& mName, const std::vector<INTERP_KERNEL::NormalizedCellType>& types, const std::vector<int>& slicPerTyp, int dt, int it, MEDFileMeshReadSelector *mrs)
+{
+  MEDFileUMeshL2 loaderl2;
+  ParaMEDMEM::MEDCouplingMeshType meshType;
+  int dummy0,dummy1;
+  std::string dummy2;
+  int mid(MEDFileUMeshL2::GetMeshIdFromName(fid,mName,meshType,dummy0,dummy1,dummy2));
+  if(meshType!=UNSTRUCTURED)
+    {
+      std::ostringstream oss; oss << "loadPartUMeshFromFile : Trying to load as unstructured an existing mesh with name '" << mName << "' !";
+      throw INTERP_KERNEL::Exception(oss.str().c_str());
+    }
+  loaderl2.loadPart(fid,mid,mName,types,slicPerTyp,dt,it,mrs);
+  dispatchLoadedPart(fid,loaderl2,mName,mrs);
+}
+
+/*!
+ * \brief Write joints in a file
+ */
+void MEDFileMesh::writeJoints(med_idt fid) const
+{
+  if ( (const MEDFileJoints*) _joints )
+    _joints->write(fid);
+}
+
+/*!
+ * \brief Load joints in a file or use provided ones
+ */
+//================================================================================
+/*!
+ * \brief Load joints in a file or use provided ones
+ *  \param [in] fid - MED file descriptor
+ *  \param [in] toUseInstedOfReading - optional joints to use instead of reading,
+ *          Usually this joints are those just read by another iteration
+ *          of namesake mesh, when this method is called by MEDFileMeshMultiTS::New()
+ */
+//================================================================================
+
+void MEDFileMesh::loadJointsFromFile(med_idt fid, MEDFileJoints* toUseInstedOfReading)
+{
+  if ( toUseInstedOfReading )
+    setJoints( toUseInstedOfReading );
+  else
+    _joints = MEDFileJoints::New( fid, _name );
+}
 
-void MEDFileUMesh::loadUMeshFromFile(med_idt fid, const char *mName, int dt, int it) throw(INTERP_KERNEL::Exception)
+/*!
+ * \brief Return number of joints, which is equal to number of adjacent mesh domains
+ */
+int MEDFileMesh::getNumberOfJoints()
+{
+  return ( (MEDFileJoints*) _joints ) ? _joints->getNumberOfJoints() : 0;
+}
+
+/*!
+ * \brief Return joints with all adjacent mesh domains
+ */
+MEDFileJoints * MEDFileMesh::getJoints() const
+{
+  return const_cast<MEDFileJoints*>(& (*_joints));
+}
+
+void MEDFileMesh::setJoints( MEDFileJoints* joints )
+{
+  if ( joints != _joints )
+    {
+      _joints = joints;
+      if ( joints )
+        joints->incrRef();
+    }
+}
+
+/*!
+ * This method loads \b all \b the \b mesh \a mName in the file with \a fid descriptor.
+ *
+ * \sa loadPartUMeshFromFile
+ */
+void MEDFileUMesh::loadUMeshFromFile(med_idt fid, const std::string& mName, int dt, int it, MEDFileMeshReadSelector *mrs)
 {
   MEDFileUMeshL2 loaderl2;
   ParaMEDMEM::MEDCouplingMeshType meshType;
   int dummy0,dummy1;
   std::string dummy2;
-  int mid=MEDFileUMeshL2::GetMeshIdFromName(fid,mName,meshType,dummy0,dummy1,dummy2);
+  int mid(MEDFileUMeshL2::GetMeshIdFromName(fid,mName,meshType,dummy0,dummy1,dummy2));
   if(meshType!=UNSTRUCTURED)
     {
       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);
+  dispatchLoadedPart(fid,loaderl2,mName,mrs);
+}
+
+void MEDFileUMesh::dispatchLoadedPart(med_idt fid, const MEDFileUMeshL2& loaderl2, const std::string& mName, MEDFileMeshReadSelector *mrs)
+{
   int lev=loaderl2.getNumberOfLevels();
   _ms.resize(lev);
   for(int i=0;i<lev;i++)
@@ -1613,17 +2528,23 @@ 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());
+  setUnivName(loaderl2.getUnivName());
   setIteration(loaderl2.getIteration());
   setOrder(loaderl2.getOrder());
   setTimeValue(loaderl2.getTime());
   setTimeUnit(loaderl2.getTimeUnit());
   _coords=loaderl2.getCoords();
-  _fam_coords=loaderl2.getCoordsFamily();
-  _num_coords=loaderl2.getCoordsNum();
+  if(!mrs || mrs->isNodeFamilyFieldReading())
+    _fam_coords=loaderl2.getCoordsFamily();
+  if(!mrs || mrs->isNodeNumFieldReading())
+    _num_coords=loaderl2.getCoordsNum();
+  if(!mrs || mrs->isNodeNameFieldReading())
+    _name_coords=loaderl2.getCoordsName();
+  _part_coords=loaderl2.getPartDefOfCoo();
   computeRevNum();
 }
 
@@ -1631,7 +2552,7 @@ MEDFileUMesh::~MEDFileUMesh()
 {
 }
 
-void MEDFileUMesh::writeLL(med_idt fid) const throw(INTERP_KERNEL::Exception)
+void MEDFileUMesh::writeLL(med_idt fid) const
 {
   const DataArrayDouble *coo=_coords;
   INTERP_KERNEL::AutoPtr<char> maa=MEDLoaderBase::buildEmptyString(MED_NAME_SIZE);
@@ -1639,7 +2560,9 @@ void MEDFileUMesh::writeLL(med_idt fid) const throw(INTERP_KERNEL::Exception)
   MEDLoaderBase::safeStrCpy(_name.c_str(),MED_NAME_SIZE,maa,_too_long_str);
   MEDLoaderBase::safeStrCpy(_desc_name.c_str(),MED_COMMENT_SIZE,desc,_too_long_str);
   int spaceDim=coo?coo->getNumberOfComponents():0;
-  int mdim=getMeshDimension();
+  int mdim(0);
+  if(!_ms.empty())
+    mdim=getMeshDimension();
   INTERP_KERNEL::AutoPtr<char> comp=MEDLoaderBase::buildEmptyString(spaceDim*MED_SNAME_SIZE);
   INTERP_KERNEL::AutoPtr<char> unit=MEDLoaderBase::buildEmptyString(spaceDim*MED_SNAME_SIZE);
   for(int i=0;i<spaceDim;i++)
@@ -1650,14 +2573,22 @@ void MEDFileUMesh::writeLL(med_idt fid) const throw(INTERP_KERNEL::Exception)
       MEDLoaderBase::safeStrCpy2(c.c_str(),MED_SNAME_SIZE-1,comp+i*MED_SNAME_SIZE,_too_long_str);//MED_TAILLE_PNOM-1 to avoid to write '\0' on next compo
       MEDLoaderBase::safeStrCpy2(u.c_str(),MED_SNAME_SIZE-1,unit+i*MED_SNAME_SIZE,_too_long_str);//MED_TAILLE_PNOM-1 to avoid to write '\0' on next compo
     }
-  MEDmeshCr(fid,maa,spaceDim,mdim,MED_UNSTRUCTURED_MESH,desc,"",MED_SORT_DTIT,MED_CARTESIAN,comp,unit);
-  MEDFileUMeshL2::WriteCoords(fid,maa,_iteration,_order,_time,_coords,_fam_coords,_num_coords);
+  MEDFILESAFECALLERWR0(MEDmeshCr,(fid,maa,spaceDim,mdim,MED_UNSTRUCTURED_MESH,desc,"",MED_SORT_DTIT,MED_CARTESIAN,comp,unit));
+  MEDFILESAFECALLERWR0(MEDmeshUniversalNameWr,(fid,maa));
+  std::string meshName(MEDLoaderBase::buildStringFromFortran(maa,MED_NAME_SIZE));
+  MEDFileUMeshL2::WriteCoords(fid,meshName,_iteration,_order,_time,_coords,_fam_coords,_num_coords,_name_coords);
   for(std::vector< MEDCouplingAutoRefCountObjectPtr<MEDFileUMeshSplitL1> >::const_iterator it=_ms.begin();it!=_ms.end();it++)
     if((const MEDFileUMeshSplitL1 *)(*it)!=0)
-      (*it)->write(fid,maa,mdim);
-  MEDFileUMeshL2::WriteFamiliesAndGrps(fid,maa,_families,_groups,_too_long_str);
+      (*it)->write(fid,meshName,mdim);
+  MEDFileUMeshL2::WriteFamiliesAndGrps(fid,meshName,_families,_groups,_too_long_str);
+
+  writeJoints(fid);
 }
 
+/*!
+ * Returns relative dimensions of mesh entities (excluding nodes) present in \a this mesh.
+ *  \return std::vector<int> - a sequence of the relative dimensions.
+ */
 std::vector<int> MEDFileUMesh::getNonEmptyLevels() const
 {
   std::vector<int> ret;
@@ -1669,6 +2600,10 @@ std::vector<int> MEDFileUMesh::getNonEmptyLevels() const
   return ret;
 }
 
+/*!
+ * Returns relative dimensions of mesh entities (including nodes) present in \a this mesh.
+ *  \return std::vector<int> - a sequence of the relative dimensions.
+ */
 std::vector<int> MEDFileUMesh::getNonEmptyLevelsExt() const
 {
   std::vector<int> ret0=getNonEmptyLevels();
@@ -1682,68 +2617,133 @@ 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;
+}
+
 /*!
- * This methods returns all relative mesh levels where group 'grp' is defined \b excluded \b nodes.
- * To include nodes call MEDFileUMesh::getGrpNonEmptyLevelsExt method.
+ * Returns all relative mesh levels (**excluding nodes**) where a given group is defined.
+ * To include nodes, call getGrpNonEmptyLevelsExt() method.
+ *  \param [in] grp - the name of the group of interest.
+ *  \return std::vector<int> - a sequence of the relative dimensions.
  */
-std::vector<int> MEDFileUMesh::getGrpNonEmptyLevels(const char *grp) const throw(INTERP_KERNEL::Exception)
+std::vector<int> MEDFileUMesh::getGrpNonEmptyLevels(const std::string& grp) const
 {
   std::vector<std::string> fams=getFamiliesOnGroup(grp);
   return getFamsNonEmptyLevels(fams);
 }
 
 /*!
- * This method is a generalization of MEDFileUMesh::getGrpNonEmptyLevelsExt. It looks at the node level to state if the group 'grp' has a part lying on node.
+ * Returns all relative mesh levels (including nodes) where a given group is defined.
+ *  \param [in] grp - the name of the group of interest.
+ *  \return std::vector<int> - a sequence of the relative dimensions.
  */
-std::vector<int> MEDFileUMesh::getGrpNonEmptyLevelsExt(const char *grp) const throw(INTERP_KERNEL::Exception)
+std::vector<int> MEDFileUMesh::getGrpNonEmptyLevelsExt(const std::string& grp) const
 {
   std::vector<std::string> fams=getFamiliesOnGroup(grp);
   return getFamsNonEmptyLevelsExt(fams);
 }
 
 /*!
- * This methods returns all relative mesh levels where family 'fam' is defined \b excluded \b nodes.
- * To include nodes call MEDFileUMesh::getFamNonEmptyLevelsExt method.
+ * Returns all relative mesh levels (**excluding nodes**) where a given family is defined.
+ * To include nodes, call getFamNonEmptyLevelsExt() method.
+ *  \param [in] fam - the name of the family of interest.
+ *  \return std::vector<int> - a sequence of the relative dimensions.
  */
-std::vector<int> MEDFileUMesh::getFamNonEmptyLevels(const char *fam) const throw(INTERP_KERNEL::Exception)
+std::vector<int> MEDFileUMesh::getFamNonEmptyLevels(const std::string& fam) const
 {
   std::vector<std::string> fams(1,std::string(fam));
   return getFamsNonEmptyLevels(fams);
 }
 
 /*!
- * This method is a generalization of MEDFileUMesh::getFamNonEmptyLevels. It looks at the node level to state if the family 'fam' has a part lying on node.
+ * Returns all relative mesh levels (including nodes) where a given family is defined.
+ *  \param [in] fam - the name of the family of interest.
+ *  \return std::vector<int> - a sequence of the relative dimensions.
  */
-std::vector<int> MEDFileUMesh::getFamNonEmptyLevelsExt(const char *fam) const throw(INTERP_KERNEL::Exception)
+std::vector<int> MEDFileUMesh::getFamNonEmptyLevelsExt(const std::string& fam) const
 {
   std::vector<std::string> fams(1,std::string(fam));
   return getFamsNonEmptyLevelsExt(fams);
 }
 
 /*!
- * This methods returns all relative mesh levels where groups 'grps' are defined \b excluded \b nodes.
- * To include nodes call MEDFileUMesh::getGrpsNonEmptyLevelsExt method.
+ * Returns all relative mesh levels (**excluding nodes**) where given groups are defined.
+ * To include nodes, call getGrpsNonEmptyLevelsExt() method.
+ *  \param [in] grps - a sequence of names of the groups of interest.
+ *  \return std::vector<int> - a sequence of the relative dimensions.
  */
-std::vector<int> MEDFileUMesh::getGrpsNonEmptyLevels(const std::vector<std::string>& grps) const throw(INTERP_KERNEL::Exception)
+std::vector<int> MEDFileUMesh::getGrpsNonEmptyLevels(const std::vector<std::string>& grps) const
 {
   std::vector<std::string> fams=getFamiliesOnGroups(grps);
   return getFamsNonEmptyLevels(fams);
 }
 
 /*!
- * This method is a generalization of MEDFileUMesh::getGrpsNonEmptyLevels. It looks at the node level to state if the families 'fams' has a part lying on node.
+ * Returns all relative mesh levels (including nodes) where given groups are defined.
+ *  \param [in] grps - a sequence of names of the groups of interest.
+ *  \return std::vector<int> - a sequence of the relative dimensions.
  */
-std::vector<int> MEDFileUMesh::getGrpsNonEmptyLevelsExt(const std::vector<std::string>& grps) const throw(INTERP_KERNEL::Exception)
+std::vector<int> MEDFileUMesh::getGrpsNonEmptyLevelsExt(const std::vector<std::string>& grps) const
 {
   std::vector<std::string> fams=getFamiliesOnGroups(grps);
   return getFamsNonEmptyLevelsExt(fams);
 }
 
 /*!
- * This methods returns all relative mesh levels where families 'fams' are defined \b excluded \b nodes.
- * To include nodes call MEDFileUMesh::getFamsNonEmptyLevelsExt method.
+ * Returns all relative mesh levels (**excluding nodes**) where given families are defined.
+ * To include nodes, call getFamsNonEmptyLevelsExt() method.
+ *  \param [in] fams - the name of the family of interest.
+ *  \return std::vector<int> - a sequence of the relative dimensions.
  */
-std::vector<int> MEDFileUMesh::getFamsNonEmptyLevels(const std::vector<std::string>& fams) const throw(INTERP_KERNEL::Exception)
+std::vector<int> MEDFileUMesh::getFamsNonEmptyLevels(const std::vector<std::string>& fams) const
 {
   std::vector<int> ret;
   std::vector<int> levs=getNonEmptyLevels();
@@ -1755,9 +2755,11 @@ std::vector<int> MEDFileUMesh::getFamsNonEmptyLevels(const std::vector<std::stri
 }
 
 /*!
- * This method is a generalization of MEDFileUMesh::getFamsNonEmptyLevels. It looks at the node level to state if the families 'fams' has a part lying on node.
+ * Returns all relative mesh levels (including nodes) where given families are defined.
+ *  \param [in] fams - the names of the families of interest.
+ *  \return std::vector<int> - a sequence of the relative dimensions.
  */
-std::vector<int> MEDFileUMesh::getFamsNonEmptyLevelsExt(const std::vector<std::string>& fams) const throw(INTERP_KERNEL::Exception)
+std::vector<int> MEDFileUMesh::getFamsNonEmptyLevelsExt(const std::vector<std::string>& fams) const
 {
   std::vector<int> ret0=getFamsNonEmptyLevels(fams);
   const DataArrayInt *famCoords=_fam_coords;
@@ -1776,22 +2778,48 @@ std::vector<int> MEDFileUMesh::getFamsNonEmptyLevelsExt(const std::vector<std::s
 }
 
 /*!
- * This method retrives all groups that partly or fully appear on the level 'meshDimRelToMaxExt'.
+ * Returns names of groups that partly or fully appear on the level \a meshDimRelToMaxExt.
+ *  \param [in] meshDimRelToMaxExt - a relative dimension of interest.
+ *  \return std::vector<std::string> - a sequence of group names at \a meshDimRelToMaxExt
+ *          level. 
  */
-std::vector<std::string> MEDFileUMesh::getGroupsOnSpecifiedLev(int meshDimRelToMaxExt) const throw(INTERP_KERNEL::Exception)
+std::vector<std::string> MEDFileUMesh::getGroupsOnSpecifiedLev(int meshDimRelToMaxExt) const
 {
   std::vector<std::string> ret;
   std::vector<std::string> allGrps=getGroupsNames();
   for(std::vector<std::string>::const_iterator it=allGrps.begin();it!=allGrps.end();it++)
     {
-      std::vector<int> levs=getGrpNonEmptyLevelsExt((*it).c_str());
+      std::vector<int> levs=getGrpNonEmptyLevelsExt((*it));
       if(std::find(levs.begin(),levs.end(),meshDimRelToMaxExt)!=levs.end())
         ret.push_back(*it);
     }
   return ret;
 }
 
-int MEDFileUMesh::getMaxFamilyIdInArrays() const throw(INTERP_KERNEL::Exception)
+int MEDFileUMesh::getMaxAbsFamilyIdInArrays() const
+{
+  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
 {
   int ret=-std::numeric_limits<int>::max(),tmp=-1;
   if((const DataArrayInt *)_fam_coords)
@@ -1806,7 +2834,7 @@ int MEDFileUMesh::getMaxFamilyIdInArrays() const throw(INTERP_KERNEL::Exception)
           const DataArrayInt *da=(*it)->getFamilyField();
           if(da)
             {
-              int val=_fam_coords->getMaxValue(tmp);
+              int val=da->getMaxValue(tmp);
               ret=std::max(ret,val);
             }
         }
@@ -1814,7 +2842,7 @@ int MEDFileUMesh::getMaxFamilyIdInArrays() const throw(INTERP_KERNEL::Exception)
   return ret;
 }
 
-int MEDFileUMesh::getMinFamilyIdInArrays() const throw(INTERP_KERNEL::Exception)
+int MEDFileUMesh::getMinFamilyIdInArrays() const
 {
   int ret=std::numeric_limits<int>::max(),tmp=-1;
   if((const DataArrayInt *)_fam_coords)
@@ -1829,7 +2857,7 @@ int MEDFileUMesh::getMinFamilyIdInArrays() const throw(INTERP_KERNEL::Exception)
           const DataArrayInt *da=(*it)->getFamilyField();
           if(da)
             {
-              int val=_fam_coords->getMinValue(tmp);
+              int val=da->getMinValue(tmp);
               ret=std::min(ret,val);
             }
         }
@@ -1837,7 +2865,12 @@ int MEDFileUMesh::getMinFamilyIdInArrays() const throw(INTERP_KERNEL::Exception)
   return ret;
 }
 
-int MEDFileUMesh::getMeshDimension() const throw(INTERP_KERNEL::Exception)
+/*!
+ * Returns the dimension on cells in \a this mesh.
+ *  \return int - the mesh dimension.
+ *  \throw If there are no cells in this mesh.
+ */
+int MEDFileUMesh::getMeshDimension() const
 {
   int lev=0;
   for(std::vector< MEDCouplingAutoRefCountObjectPtr<MEDFileUMeshSplitL1> >::const_iterator it=_ms.begin();it!=_ms.end();it++,lev++)
@@ -1846,7 +2879,13 @@ int MEDFileUMesh::getMeshDimension() const throw(INTERP_KERNEL::Exception)
   throw INTERP_KERNEL::Exception("MEDFileUMesh::getMeshDimension : impossible to find a mesh dimension !");
 }
 
-int MEDFileUMesh::getSpaceDimension() const throw(INTERP_KERNEL::Exception)
+/*!
+ * Returns the space dimension of \a this mesh that is equal to number of components in
+ * the node coordinates array.
+ *  \return int - the space dimension of \a this mesh.
+ *  \throw If the node coordinates array is not available.
+ */
+int MEDFileUMesh::getSpaceDimension() const
 {
   const DataArrayDouble *coo=_coords;
   if(!coo)
@@ -1854,6 +2893,10 @@ int MEDFileUMesh::getSpaceDimension() const throw(INTERP_KERNEL::Exception)
   return coo->getNumberOfComponents();
 }
 
+/*!
+ * Returns a string describing \a this mesh.
+ *  \return std::string - the mesh information string.
+ */
 std::string MEDFileUMesh::simpleRepr() const
 {
   std::ostringstream oss;
@@ -1902,12 +2945,22 @@ std::string MEDFileUMesh::simpleRepr() const
   return oss.str();
 }
 
+/*!
+ * Returns a full textual description of \a this mesh.
+ *  \return std::string - the string holding the mesh description.
+ */
 std::string MEDFileUMesh::advancedRepr() const
 {
   return simpleRepr();
 }
 
-int MEDFileUMesh::getSizeAtLevel(int meshDimRelToMaxExt) const throw(INTERP_KERNEL::Exception)
+/*!
+ * Returns number of mesh entities of a given relative dimension in \a this mesh.
+ *  \param [in] meshDimRelToMaxExt - the relative dimension of interest.
+ *  \return int - the number of entities.
+ *  \throw If no mesh entities of dimension \a meshDimRelToMaxExt are available in \a this mesh.
+ */
+int MEDFileUMesh::getSizeAtLevel(int meshDimRelToMaxExt) const
 {
   if(meshDimRelToMaxExt==1)
     {
@@ -1918,31 +2971,120 @@ int MEDFileUMesh::getSizeAtLevel(int meshDimRelToMaxExt) const throw(INTERP_KERN
   return getMeshAtLevSafe(meshDimRelToMaxExt)->getSize();
 }
 
-const DataArrayInt *MEDFileUMesh::getFamilyFieldAtLevel(int meshDimRelToMaxExt) const throw(INTERP_KERNEL::Exception)
+/*!
+ * Returns the family field for mesh entities of a given dimension.
+ *  \param [in] meshDimRelToMaxExt - the relative dimension of mesh entities.
+ *  \return const DataArrayInt * - the family field. It is an array of ids of families
+ *          each mesh entity belongs to. It can be \c NULL.
+ */
+const DataArrayInt *MEDFileUMesh::getFamilyFieldAtLevel(int meshDimRelToMaxExt) const
 {
   if(meshDimRelToMaxExt==1)
     return _fam_coords;
-  const MEDFileUMeshSplitL1 *l1=getMeshAtLevSafe(meshDimRelToMaxExt);
+  const MEDFileUMeshSplitL1 *l1(getMeshAtLevSafe(meshDimRelToMaxExt));
   return l1->getFamilyField();
 }
 
-const DataArrayInt *MEDFileUMesh::getNumberFieldAtLevel(int meshDimRelToMaxExt) const throw(INTERP_KERNEL::Exception)
+DataArrayInt *MEDFileUMesh::getFamilyFieldAtLevel(int meshDimRelToMaxExt)
 {
   if(meshDimRelToMaxExt==1)
-    return _num_coords;
-  const MEDFileUMeshSplitL1 *l1=getMeshAtLevSafe(meshDimRelToMaxExt);
-  return l1->getNumberField();
+    return _fam_coords;
+  MEDFileUMeshSplitL1 *l1(getMeshAtLevSafe(meshDimRelToMaxExt));
+  return l1->getFamilyField();
 }
 
-int MEDFileUMesh::getNumberOfNodes() const throw(INTERP_KERNEL::Exception)
+/*!
+ * Returns the optional numbers of mesh entities of a given dimension.
+ *  \param [in] meshDimRelToMaxExt - the relative dimension of mesh entities.
+ *  \return const DataArrayInt * - the array of the entity numbers.
+ *  \throw If there are no mesh entities of \a meshDimRelToMaxExt dimension in \a this mesh.
+ */
+const DataArrayInt *MEDFileUMesh::getNumberFieldAtLevel(int meshDimRelToMaxExt) const
 {
-  const DataArrayDouble *coo=_coords;
+  if(meshDimRelToMaxExt==1)
+    return _num_coords;
+  const MEDFileUMeshSplitL1 *l1=getMeshAtLevSafe(meshDimRelToMaxExt);
+  return l1->getNumberField();
+}
+
+const DataArrayAsciiChar *MEDFileUMesh::getNameFieldAtLevel(int meshDimRelToMaxExt) const
+{
+  if(meshDimRelToMaxExt==1)
+    return _name_coords;
+  const MEDFileUMeshSplitL1 *l1=getMeshAtLevSafe(meshDimRelToMaxExt);
+  return l1->getNameField();
+}
+
+/*!
+ * This method returns for a specified relative level \a meshDimRelToMaxExt the part effectively read (if the instance is the result of the read of a file).
+ *
+ * \param [in] meshDimRelToMaxExt - the extended relative level for which the part definition is requested.
+ * \param [in] gt - The input geometric type for which the part definition is requested.
+ * \return the part definition owned by \a this. So no need to deallocate the returned instance.
+ */
+const PartDefinition *MEDFileUMesh::getPartDefAtLevel(int meshDimRelToMaxExt, INTERP_KERNEL::NormalizedCellType gt) const
+{
+  if(meshDimRelToMaxExt==1)
+    return _part_coords;
+  const MEDFileUMeshSplitL1 *l1(getMeshAtLevSafe(meshDimRelToMaxExt));
+  return l1->getPartDef(gt);
+}
+
+int MEDFileUMesh::getNumberOfNodes() const
+{
+  const DataArrayDouble *coo(_coords);
   if(!coo)
     throw INTERP_KERNEL::Exception(" MEDFileUMesh::getNumberOfNodes : no coords set !");
   return coo->getNumberOfTuples();
 }
 
-const DataArrayInt *MEDFileUMesh::getRevNumberFieldAtLevel(int meshDimRelToMaxExt) const throw(INTERP_KERNEL::Exception)
+int MEDFileUMesh::getNumberOfCellsAtLevel(int meshDimRelToMaxExt) const
+{
+  const MEDFileUMeshSplitL1 *l1(getMeshAtLevSafe(meshDimRelToMaxExt));
+  return l1->getNumberOfCells();
+}
+
+bool MEDFileUMesh::hasImplicitPart() const
+{
+  return false;
+}
+
+int MEDFileUMesh::buildImplicitPartIfAny(INTERP_KERNEL::NormalizedCellType gt) const
+{
+  throw INTERP_KERNEL::Exception("MEDFileUMesh::buildImplicitPartIfAny : unstructured meshes do not have implicit part !");
+}
+
+void MEDFileUMesh::releaseImplicitPartIfAny() const
+{
+}
+
+void MEDFileUMesh::whichAreNodesFetched(const MEDFileField1TSStructItem& st, const MEDFileFieldGlobsReal *globs, std::vector<bool>& nodesFetched) const
+{
+  std::size_t sz(st.getNumberOfItems());
+  for(std::size_t i=0;i<sz;i++)
+    {
+      INTERP_KERNEL::NormalizedCellType curGt(st[i].getGeo());
+      const MEDCoupling1GTUMesh *m(getDirectUndergroundSingleGeoTypeMesh(curGt));
+      if(st[i].getPflName().empty())
+        m->computeNodeIdsAlg(nodesFetched);
+      else
+        {
+          const DataArrayInt *arr(globs->getProfile(st[i].getPflName()));
+          MEDCouplingAutoRefCountObjectPtr<MEDCoupling1GTUMesh> m2(dynamic_cast<MEDCoupling1GTUMesh *>(m->buildPartOfMySelf(arr->begin(),arr->end(),true)));
+          m2->computeNodeIdsAlg(nodesFetched);
+        }
+    }
+}
+
+/*!
+ * Returns the optional numbers of mesh entities of a given dimension transformed using
+ * DataArrayInt::invertArrayN2O2O2N().
+ *  \param [in] meshDimRelToMaxExt - the relative dimension of mesh entities.
+ *  \return const DataArrayInt * - the array of the entity numbers transformed using
+ *          DataArrayInt::invertArrayN2O2O2N().
+ *  \throw If there are no mesh entities of \a meshDimRelToMaxExt dimension in \a this mesh.
+ */
+const DataArrayInt *MEDFileUMesh::getRevNumberFieldAtLevel(int meshDimRelToMaxExt) const
 {
   if(meshDimRelToMaxExt==1)
     {
@@ -1955,7 +3097,8 @@ const DataArrayInt *MEDFileUMesh::getRevNumberFieldAtLevel(int meshDimRelToMaxEx
 }
 
 /*!
- * This method returns coordinates in 'this'. The returned array reference counter is \b not incremented by this method (as MEDCouplingPointSet::getCoords does).
+ * Returns a pointer to the node coordinates array of \a this mesh \b without
+ * incrementing its reference counter, thus there is no need to decrRef() it by the caller.
  */
 DataArrayDouble *MEDFileUMesh::getCoords() const
 {
@@ -1967,34 +3110,89 @@ DataArrayDouble *MEDFileUMesh::getCoords() const
   return 0;
 }
 
-MEDCouplingUMesh *MEDFileUMesh::getGroup(int meshDimRelToMaxExt, const char *grp, bool renum) const throw(INTERP_KERNEL::Exception)
+/*!
+ * Returns a new MEDCouplingUMesh corresponding to mesh entities included in a given
+ * group of \a this mesh. Only mesh entities of a given dimension are included in the
+ * new mesh.
+ *  \param [in] meshDimRelToMaxExt - the relative dimension of mesh entities of interest.
+ *  \param [in] grp - the name of the group whose mesh entities are included in the
+ *          new mesh.
+ *  \param [in] renum - if \c true, cells and nodes of the result mesh are permuted
+ *          according to the optional numbers of entities, if available.
+ *  \return MEDCouplingUMesh * - a new instance of MEDCouplingUMesh. The caller is to
+ *          delete this mesh using decrRef() as it is no more needed.
+ *  \throw If the name of a nonexistent group is specified.
+ *  \throw If there are no mesh entities of \a meshDimRelToMaxExt dimension in \a this mesh.
+ */
+MEDCouplingUMesh *MEDFileUMesh::getGroup(int meshDimRelToMaxExt, const std::string& grp, bool renum) const
 {
   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);
 }
 
-MEDCouplingUMesh *MEDFileUMesh::getGroups(int meshDimRelToMaxExt, const std::vector<std::string>& grps, bool renum) const throw(INTERP_KERNEL::Exception)
+/*!
+ * Returns a new MEDCouplingUMesh corresponding to mesh entities included in given
+ * groups of \a this mesh. Only mesh entities of a given dimension are included in the
+ * new mesh.
+ *  \param [in] meshDimRelToMaxExt - the relative dimension of mesh entities of interest.
+ *  \param [in] grps - a sequence of group names whose mesh entities are included in the
+ *          new mesh.
+ *  \param [in] renum - if \c true, cells and nodes of the result mesh are permuted
+ *          according to the optional numbers of entities, if available.
+ *  \return MEDCouplingUMesh * - a new instance of MEDCouplingUMesh. The caller is to
+ *          delete this mesh using decrRef() as it is no more needed.
+ *  \throw If a name of a nonexistent group is present in \a grps.
+ *  \throw If there are no mesh entities of \a meshDimRelToMaxExt dimension in \a this mesh.
+ */
+MEDCouplingUMesh *MEDFileUMesh::getGroups(int meshDimRelToMaxExt, const std::vector<std::string>& grps, bool renum) const
 {
   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]);
+  return zeRet.retn();
 }
 
-MEDCouplingUMesh *MEDFileUMesh::getFamily(int meshDimRelToMaxExt, const char *fam, bool renum) const throw(INTERP_KERNEL::Exception)
+/*!
+ * Returns a new MEDCouplingUMesh corresponding to mesh entities included in a given
+ * family of \a this mesh. Only mesh entities of a given dimension are included in the
+ * new mesh.
+ *  \param [in] meshDimRelToMaxExt - the relative dimension of mesh entities of interest.
+ *  \param [in] fam - the name of the family whose mesh entities are included in the
+ *          new mesh.
+ *  \param [in] renum - if \c true, cells and nodes of the result mesh are permuted
+ *          according to the optional numbers of entities, if available.
+ *  \return MEDCouplingUMesh * - a new instance of MEDCouplingUMesh. The caller is to
+ *          delete this mesh using decrRef() as it is no more needed.
+ *  \throw If a name of a nonexistent family is present in \a grps.
+ *  \throw If there are no mesh entities of \a meshDimRelToMaxExt dimension in \a this mesh.
+ */
+MEDCouplingUMesh *MEDFileUMesh::getFamily(int meshDimRelToMaxExt, const std::string& fam, bool renum) const
 {
   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);
 }
 
-MEDCouplingUMesh *MEDFileUMesh::getFamilies(int meshDimRelToMaxExt, const std::vector<std::string>& fams, bool renum) const throw(INTERP_KERNEL::Exception)
+/*!
+ * Returns a new MEDCouplingUMesh corresponding to mesh entities included in given
+ * families of \a this mesh. Only mesh entities of a given dimension are included in the
+ * new mesh.
+ *  \param [in] meshDimRelToMaxExt - the relative dimension of mesh entities of interest.
+ *  \param [in] fams - a sequence of family names whose mesh entities are included in the
+ *          new mesh.
+ *  \param [in] renum - if \c true, cells and nodes of the result mesh are permuted
+ *          according to the optional numbers of entities, if available.
+ *  \return MEDCouplingUMesh * - a new instance of MEDCouplingUMesh. The caller is to
+ *          delete this mesh using decrRef() as it is no more needed.
+ *  \throw If a name of a nonexistent family is present in \a fams.
+ *  \throw If there are no mesh entities of \a meshDimRelToMaxExt dimension in \a this mesh.
+ */
+MEDCouplingUMesh *MEDFileUMesh::getFamilies(int meshDimRelToMaxExt, const std::vector<std::string>& fams, bool renum) const
 {
   synchronizeTinyInfoOnLeaves();
   if(meshDimRelToMaxExt==1)
@@ -2007,13 +3205,29 @@ 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]);
+  return zeRet.retn();
 }
 
-DataArrayInt *MEDFileUMesh::getFamiliesArr(int meshDimRelToMaxExt, const std::vector<std::string>& fams, bool renum) const throw(INTERP_KERNEL::Exception)
+/*!
+ * Returns ids of mesh entities contained in given families of a given dimension.
+ *  \param [in] meshDimRelToMaxExt - a relative dimension of the mesh entities whose ids
+ *          are required.
+ *  \param [in] fams - the names of the families of interest.
+ *  \param [in] renum - if \c true, the optional numbers of entities, if available, are
+ *          returned instead of ids.
+ *  \return DataArrayInt * - a new instance of DataArrayInt holding either ids or
+ *          numbers, if available and required, of mesh entities of the families. The caller
+ *          is to delete this array using decrRef() as it is no more needed. 
+ *  \throw If the family field is missing for \a meshDimRelToMaxExt.
+ */
+DataArrayInt *MEDFileUMesh::getFamiliesArr(int meshDimRelToMaxExt, const std::vector<std::string>& fams, bool renum) const
 {
   std::vector<int> famIds=getFamiliesIds(fams);
   if(meshDimRelToMaxExt==1)
@@ -2041,13 +3255,20 @@ DataArrayInt *MEDFileUMesh::getFamiliesArr(int meshDimRelToMaxExt, const std::ve
 }
 
 /*!
- * Returns a pointer to mesh at the specified level.
- * 
- * \return a pointer to unstructured mesh that need to be managed by the caller.
- * \warning the returned pointer has to be managed by the caller.
- * \sa MEDFileUMesh::getGenMeshAtLevel
+ * Returns a MEDCouplingUMesh of a given relative dimension.
+ * \warning If \a meshDimRelToMaxExt == 1 (which means nodes), the returned mesh **is not
+ * valid**. This is a feature, because MEDLoader does not create cells that do not exist! 
+ * To build a valid MEDCouplingUMesh from the returned one in this case,
+ * call MEDCouplingUMesh::Build0DMeshFromCoords().
+ *  \param [in] meshDimRelToMax - the relative dimension of interest.
+ *  \param [in] renum - if \c true, the returned mesh is permuted according to the
+ *          optional numbers of mesh entities.
+ *  \return MEDCouplingUMesh * - a pointer to MEDCouplingUMesh that the caller is to
+ *          delete using decrRef() as it is no more needed. 
+ *  \throw If there are no mesh entities of \a meshDimRelToMaxExt dimension in \a this mesh.
+ * \sa getGenMeshAtLevel()
  */
-MEDCouplingUMesh *MEDFileUMesh::getMeshAtLevel(int meshDimRelToMaxExt, bool renum) const throw(INTERP_KERNEL::Exception)
+MEDCouplingUMesh *MEDFileUMesh::getMeshAtLevel(int meshDimRelToMaxExt, bool renum) const
 {
   synchronizeTinyInfoOnLeaves();
   if(meshDimRelToMaxExt==1)
@@ -2067,38 +3288,176 @@ MEDCouplingUMesh *MEDFileUMesh::getMeshAtLevel(int meshDimRelToMaxExt, bool renu
 }
 
 /*!
- * Returns a pointer to mesh at the specified level.
- * 
- * \return a pointer to unstructured mesh that need to be managed by the caller.
- * \warning the returned pointer has to be managed by the caller.
- * \sa MEDFileUMesh::getMeshAtLevel
+ * Returns a MEDCouplingUMesh of a given relative dimension.
+ * \warning If \a meshDimRelToMaxExt == 1 (which means nodes), the returned mesh **is not
+ * valid**. This is a feature, because MEDLoader does not create cells that do not exist! 
+ * To build a valid MEDCouplingUMesh from the returned one in this case,
+ * call MEDCouplingUMesh::Build0DMeshFromCoords().
+ *  \param [in] meshDimRelToMax - the relative dimension of interest.
+ *  \param [in] renum - if \c true, the returned mesh is permuted according to the
+ *          optional numbers of mesh entities.
+ *  \return MEDCouplingMesh * - a pointer to MEDCouplingUMesh that the caller is to
+ *          delete using decrRef() as it is no more needed. 
+ *  \throw If there are no mesh entities of \a meshDimRelToMax dimension in \a this mesh.
+ * \sa getMeshAtLevel()
  */
-MEDCouplingMesh *MEDFileUMesh::getGenMeshAtLevel(int meshDimRelToMax, bool renum) const throw(INTERP_KERNEL::Exception)
+MEDCouplingMesh *MEDFileUMesh::getGenMeshAtLevel(int meshDimRelToMax, bool renum) const
 {
   return getMeshAtLevel(meshDimRelToMax,renum);
 }
 
-MEDCouplingUMesh *MEDFileUMesh::getLevel0Mesh(bool renum) const throw(INTERP_KERNEL::Exception)
+std::vector<int> MEDFileUMesh::getDistributionOfTypes(int meshDimRelToMax) const
+{
+  const MEDFileUMeshSplitL1 *l1(getMeshAtLevSafe(meshDimRelToMax));
+  return l1->getDistributionOfTypes();
+}
+
+/*!
+ * Returns a MEDCouplingUMesh of a relative dimension == 0.
+ *  \param [in] renum - if \c true, the returned mesh is permuted according to the
+ *          optional numbers of mesh entities.
+ *  \return MEDCouplingUMesh * - a pointer to MEDCouplingUMesh that the caller is to
+ *          delete using decrRef() as it is no more needed. 
+ *  \throw If there are no mesh entities of the relative dimension == 0 in \a this mesh.
+ */
+MEDCouplingUMesh *MEDFileUMesh::getLevel0Mesh(bool renum) const
 {
   return getMeshAtLevel(0,renum);
 }
 
-MEDCouplingUMesh *MEDFileUMesh::getLevelM1Mesh(bool renum) const throw(INTERP_KERNEL::Exception)
+/*!
+ * Returns a MEDCouplingUMesh of a relative dimension == -1.
+ *  \param [in] renum - if \c true, the returned mesh is permuted according to the
+ *          optional numbers of mesh entities.
+ *  \return MEDCouplingUMesh * - a pointer to MEDCouplingUMesh that the caller is to
+ *          delete using decrRef() as it is no more needed. 
+ *  \throw If there are no mesh entities of the relative dimension == -1 in \a this mesh.
+ */
+MEDCouplingUMesh *MEDFileUMesh::getLevelM1Mesh(bool renum) const
 {
   return getMeshAtLevel(-1,renum);
 }
 
-MEDCouplingUMesh *MEDFileUMesh::getLevelM2Mesh(bool renum) const throw(INTERP_KERNEL::Exception)
+/*!
+ * Returns a MEDCouplingUMesh of a relative dimension == -2.
+ *  \param [in] renum - if \c true, the returned mesh is permuted according to the
+ *          optional numbers of mesh entities.
+ *  \return MEDCouplingUMesh * - a pointer to MEDCouplingUMesh that the caller is to
+ *          delete using decrRef() as it is no more needed. 
+ *  \throw If there are no mesh entities of the relative dimension == -2 in \a this mesh.
+ */
+MEDCouplingUMesh *MEDFileUMesh::getLevelM2Mesh(bool renum) const
 {
   return getMeshAtLevel(-2,renum);
 }
 
-MEDCouplingUMesh *MEDFileUMesh::getLevelM3Mesh(bool renum) const throw(INTERP_KERNEL::Exception)
+/*!
+ * Returns a MEDCouplingUMesh of a relative dimension == -3.
+ *  \param [in] renum - if \c true, the returned mesh is permuted according to the
+ *          optional numbers of mesh entities.
+ *  \return MEDCouplingUMesh * - a pointer to MEDCouplingUMesh that the caller is to
+ *          delete using decrRef() as it is no more needed. 
+ *  \throw If there are no mesh entities of the relative dimension == -3 in \a this mesh.
+ */
+MEDCouplingUMesh *MEDFileUMesh::getLevelM3Mesh(bool renum) const
 {
   return getMeshAtLevel(-3,renum);
 }
 
-const MEDFileUMeshSplitL1 *MEDFileUMesh::getMeshAtLevSafe(int meshDimRelToMaxExt) const throw(INTERP_KERNEL::Exception)
+/*!
+ * This method is for advanced users. There is two storing strategy of mesh in \a this.
+ * Either MEDCouplingUMesh, or vector of MEDCoupling1GTUMesh instances.
+ * When assignement is done the first one is done, which is not optimal in write mode for MED file.
+ * This method allows to switch from MEDCouplingUMesh mode to MEDCoupling1GTUMesh mode.
+ */
+void MEDFileUMesh::forceComputationOfParts() const
+{
+  for(std::vector< MEDCouplingAutoRefCountObjectPtr<MEDFileUMeshSplitL1> >::const_iterator it=_ms.begin();it!=_ms.end();it++)
+    {
+      const MEDFileUMeshSplitL1 *elt(*it);
+      if(elt)
+        elt->forceComputationOfParts();
+    }
+}
+
+/*!
+ * 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.
+ * The returned pointers are **NOT** new object pointer. No need to mange them.
+ */
+std::vector<MEDCoupling1GTUMesh *> MEDFileUMesh::getDirectUndergroundSingleGeoTypeMeshes(int meshDimRelToMax) const
+{
+  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.
+ * The returned pointer is **NOT** new object pointer. No need to mange it.
+ */
+MEDCoupling1GTUMesh *MEDFileUMesh::getDirectUndergroundSingleGeoTypeMesh(INTERP_KERNEL::NormalizedCellType gt) const
+{
+  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);
+}
+
+/*!
+ * Given a relative level \a meshDimRelToMax it returns the sorted vector of geometric types present in \a this.
+ * \throw if the reqsuested \a meshDimRelToMax does not exist.
+ */
+std::vector<INTERP_KERNEL::NormalizedCellType> MEDFileUMesh::getGeoTypesAtLevel(int meshDimRelToMax) const
+{
+  const MEDFileUMeshSplitL1 *sp(getMeshAtLevSafe(meshDimRelToMax));
+  return sp->getGeoTypes();
+}
+
+/*!
+ * This method extracts from whole family field ids the part relative to the input parameter \a gt.
+ * \param [in] gt - the geometric type for which the family field is asked.
+ * \return DataArrayInt * - a pointer to DataArrayInt that the caller is to
+ *          delete using decrRef() as it is no more needed.
+ * \sa MEDFileUMesh::extractNumberFieldOnGeoType
+ */
+DataArrayInt *MEDFileUMesh::extractFamilyFieldOnGeoType(INTERP_KERNEL::NormalizedCellType gt) const
+{
+  const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel(gt);
+  int lev=(int)cm.getDimension()-getMeshDimension();
+  const MEDFileUMeshSplitL1 *sp(getMeshAtLevSafe(lev));
+  return sp->extractFamilyFieldOnGeoType(gt);
+}
+
+/*!
+ * This method extracts from whole number field ids the part relative to the input parameter \a gt.
+ * \param [in] gt - the geometric type for which the number field is asked.
+ * \return DataArrayInt * - a pointer to DataArrayInt that the caller is to
+ *          delete using decrRef() as it is no more needed.
+ * \sa MEDFileUMesh::extractFamilyFieldOnGeoType
+ */
+DataArrayInt *MEDFileUMesh::extractNumberFieldOnGeoType(INTERP_KERNEL::NormalizedCellType gt) const
+{
+  const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel(gt);
+  int lev=(int)cm.getDimension()-getMeshDimension();
+  const MEDFileUMeshSplitL1 *sp(getMeshAtLevSafe(lev));
+  return sp->extractNumberFieldOnGeoType(gt);
+}
+
+/*!
+ * This method returns for specified geometric type \a gt the relative level to \a this.
+ * If the relative level is empty an exception will be thrown.
+ */
+int MEDFileUMesh::getRelativeLevOnGeoType(INTERP_KERNEL::NormalizedCellType gt) const
+{
+  const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel(gt);
+  int ret((int)cm.getDimension()-getMeshDimension());
+  getMeshAtLevSafe(ret);//To test that returned value corresponds to a valid level.
+  return ret;
+}
+
+const MEDFileUMeshSplitL1 *MEDFileUMesh::getMeshAtLevSafe(int meshDimRelToMaxExt) const
 {
   if(meshDimRelToMaxExt==1)
     throw INTERP_KERNEL::Exception("Dimension request is invalid : asking for node level (1) !");
@@ -2106,27 +3465,27 @@ const MEDFileUMeshSplitL1 *MEDFileUMesh::getMeshAtLevSafe(int meshDimRelToMaxExt
     throw INTERP_KERNEL::Exception("Dimension request is invalid (>1) !");
   int tracucedRk=-meshDimRelToMaxExt;
   if(tracucedRk>=(int)_ms.size())
-    throw INTERP_KERNEL::Exception("Invalid mesh dim relative to max given ! To low !");
+    throw INTERP_KERNEL::Exception("Invalid mesh dim relative to max given ! Too low !");
   if((const MEDFileUMeshSplitL1 *)_ms[tracucedRk]==0)
     throw INTERP_KERNEL::Exception("On specified lev (or entity) no cells exists !");
   return _ms[tracucedRk];
 }
 
-MEDFileUMeshSplitL1 *MEDFileUMesh::getMeshAtLevSafe(int meshDimRelToMaxExt) throw(INTERP_KERNEL::Exception)
+MEDFileUMeshSplitL1 *MEDFileUMesh::getMeshAtLevSafe(int meshDimRelToMaxExt)
 {
-   if(meshDimRelToMaxExt==1)
+  if(meshDimRelToMaxExt==1)
     throw INTERP_KERNEL::Exception("Dimension request is invalid : asking for node level (1) !");
   if(meshDimRelToMaxExt>1)
     throw INTERP_KERNEL::Exception("Dimension request is invalid (>1) !");
   int tracucedRk=-meshDimRelToMaxExt;
   if(tracucedRk>=(int)_ms.size())
-    throw INTERP_KERNEL::Exception("Invalid mesh dim relative to max given ! To low !");
+    throw INTERP_KERNEL::Exception("Invalid mesh dim relative to max given ! Too low !");
   if((const MEDFileUMeshSplitL1 *)_ms[tracucedRk]==0)
     throw INTERP_KERNEL::Exception("On specified lev (or entity) no cells exists !");
   return _ms[tracucedRk];
 }
 
-void MEDFileUMesh::checkMeshDimCoherency(int meshDim, int meshDimRelToMax) const throw(INTERP_KERNEL::Exception)
+void MEDFileUMesh::checkMeshDimCoherency(int meshDim, int meshDimRelToMax) const
 {
   if(-meshDimRelToMax>=(int)_ms.size())
     throw INTERP_KERNEL::Exception("MEDFileUMesh::checkMeshDimCoherency : The meshdim of mesh is not managed by 'this' !");
@@ -2142,7 +3501,12 @@ void MEDFileUMesh::checkMeshDimCoherency(int meshDim, int meshDimRelToMax) const
     }
 }
 
-void MEDFileUMesh::setCoords(DataArrayDouble *coords) throw(INTERP_KERNEL::Exception)
+/*!
+ * Sets the node coordinates array of \a this mesh.
+ *  \param [in] coords - the new node coordinates array.
+ *  \throw If \a coords == \c NULL.
+ */
+void MEDFileUMesh::setCoords(DataArrayDouble *coords)
 {
   if(!coords)
     throw INTERP_KERNEL::Exception("MEDFileUMesh::setCoords : null pointer in input !");
@@ -2153,9 +3517,17 @@ 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);
 }
 
-void MEDFileUMesh::eraseGroupsAtLevel(int meshDimRelToMaxExt) throw(INTERP_KERNEL::Exception)
+/*!
+ * Removes all groups of a given dimension in \a this mesh.
+ *  \param [in] meshDimRelToMaxExt - the relative dimension of interest.
+ *  \throw If there are no mesh entities of \a meshDimRelToMaxExt dimension in \a this mesh.
+ */
+void MEDFileUMesh::eraseGroupsAtLevel(int meshDimRelToMaxExt)
 {
   if(meshDimRelToMaxExt==1)
     {
@@ -2168,16 +3540,19 @@ void MEDFileUMesh::eraseGroupsAtLevel(int meshDimRelToMaxExt) throw(INTERP_KERNE
   optimizeFamilies();
 }
 
-void MEDFileUMesh::optimizeFamilies() throw(INTERP_KERNEL::Exception)
+/*!
+ * Removes all families with ids not present in the family fields of \a this mesh.
+ */
+void MEDFileUMesh::optimizeFamilies()
 {
   std::vector<int> levs=getNonEmptyLevelsExt();
   std::set<int> allFamsIds;
   for(std::vector<int>::const_iterator it=levs.begin();it!=levs.end();it++)
     {
       const DataArrayInt *ffield=getFamilyFieldAtLevel(*it);
-      std::set<int> ids=ffield->getDifferentValues();
+      MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ids=ffield->getDifferentValues();
       std::set<int> res;
-      std::set_union(ids.begin(),ids.end(),allFamsIds.begin(),allFamsIds.end(),std::inserter(res,res.begin()));
+      std::set_union(ids->begin(),ids->end(),allFamsIds.begin(),allFamsIds.end(),std::inserter(res,res.begin()));
       allFamsIds=res;
     }
   std::set<std::string> famNamesToKill;
@@ -2206,7 +3581,7 @@ void MEDFileUMesh::optimizeFamilies() throw(INTERP_KERNEL::Exception)
     _groups.erase(*it);
 }
 
-void MEDFileUMesh::duplicateNodesOnM1Group(const char *grpNameM1, DataArrayInt *&nodesDuplicated, DataArrayInt *&cellsModified, DataArrayInt *&cellsNotModified) throw(INTERP_KERNEL::Exception)
+void MEDFileUMesh::duplicateNodesOnM1Group(const std::string& grpNameM1, DataArrayInt *&nodesDuplicated, DataArrayInt *&cellsModified, DataArrayInt *&cellsNotModified)
 {
   std::vector<int> levs=getNonEmptyLevels();
   if(std::find(levs.begin(),levs.end(),0)==levs.end() || std::find(levs.begin(),levs.end(),-1)==levs.end())
@@ -2279,8 +3654,8 @@ void MEDFileUMesh::duplicateNodesOnM1Group(const char *grpNameM1, DataArrayInt *
   setMeshAtLevel(-1,newm1);
   setFamilyFieldArr(-1,newFam);
   std::string grpName2(grpNameM1); grpName2+="_dup";
-  addFamily(grpName2.c_str(),idd);
-  addFamilyOnGrp(grpName2.c_str(),grpName2.c_str());
+  addFamily(grpName2,idd);
+  addFamilyOnGrp(grpName2,grpName2);
   //
   fam=_fam_coords;
   if(fam)
@@ -2304,7 +3679,7 @@ void MEDFileUMesh::duplicateNodesOnM1Group(const char *grpNameM1, DataArrayInt *
  * \return false if no modification has been performed linked to the unpolyzation. Neither cell type, not cell numbers. When false is returned no need of field on cells or on gauss renumbering.
  * Inversely, if true is returned, it means that distribution of cell by geometric type has changed and field on cell and field on gauss point must be renumbered.
  */
-bool MEDFileUMesh::unPolyze(std::vector<int>& oldCode, std::vector<int>& newCode, DataArrayInt *& o2nRenumCell) throw(INTERP_KERNEL::Exception)
+bool MEDFileUMesh::unPolyze(std::vector<int>& oldCode, std::vector<int>& newCode, DataArrayInt *& o2nRenumCell)
 {
   o2nRenumCell=0; oldCode.clear(); newCode.clear();
   std::vector<int> levs=getNonEmptyLevels();
@@ -2322,7 +3697,7 @@ bool MEDFileUMesh::unPolyze(std::vector<int>& oldCode, std::vector<int>& newCode
       bool hasChanged=m->unPolyze();
       DataArrayInt *fake=0;
       MEDCouplingAutoRefCountObjectPtr<DataArrayInt> o2nCellsPart=m->getLevArrPerCellTypes(MEDCouplingUMesh::MEDMEM_ORDER,
-                                                                                           MEDCouplingUMesh::MEDMEM_ORDER+MEDCouplingUMesh::N_MEDMEM_ORDER,fake);
+          MEDCouplingUMesh::MEDMEM_ORDER+MEDCouplingUMesh::N_MEDMEM_ORDER,fake);
       fake->decrRef();
       renumCellsSplited.push_back(o2nCellsPart); memorySaverIfThrow.push_back(o2nCellsPart);
       if(hasChanged)
@@ -2379,186 +3754,611 @@ struct MEDLoaderAccVisit1
  * The size of returned array is the number of nodes of the old (previous to the call of this method) number of nodes.
  * -1 values in returned array means that the corresponding old node is no more used.
  *
- * \return newly allocated array containing correspondance in \b old \b to \b new format. If all nodes in \a this are fetched NULL pointer is returned and nothing
+ * \return newly allocated array containing correspondance in \b old \b to \b new format. If all nodes in \a this are fetched \c NULL pointer is returned and nothing
  *         is modified in \a this.
  * \throw If no coordinates are set in \a this or if there is in any available mesh in \a this a cell having a nodal connectivity containing a node id not in the range of
  *  set coordinates.
  */
-DataArrayInt *MEDFileUMesh::zipCoords() throw(INTERP_KERNEL::Exception)
+DataArrayInt *MEDFileUMesh::zipCoords()
 {
-  const DataArrayDouble *coo=getCoords();
+  const DataArrayDouble *coo(getCoords());
   if(!coo)
     throw INTERP_KERNEL::Exception("MEDFileUMesh::zipCoords : no coordinates set in this !");
-  int nbOfNodes=coo->getNumberOfTuples();
+  int nbOfNodes(coo->getNumberOfTuples());
   std::vector<bool> nodeIdsInUse(nbOfNodes,false);
-  std::vector<int> neLevs=getNonEmptyLevels();
+  std::vector<int> neLevs(getNonEmptyLevels());
   for(std::vector<int>::const_iterator lev=neLevs.begin();lev!=neLevs.end();lev++)
     {
-      MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> m=getMeshAtLevel(*lev);
-      m->computeNodeIdsAlg(nodeIdsInUse);
+      const MEDFileUMeshSplitL1 *zeLev(getMeshAtLevSafe(*lev));
+      if(zeLev->isMeshStoredSplitByType())
+        {
+          std::vector<MEDCoupling1GTUMesh *> ms(zeLev->getDirectUndergroundSingleGeoTypeMeshes());
+          for(std::vector<MEDCoupling1GTUMesh *>::const_iterator it=ms.begin();it!=ms.end();it++)
+            if(*it)
+              (*it)->computeNodeIdsAlg(nodeIdsInUse);
+        }
+      else
+        {
+          MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> mesh(zeLev->getWholeMesh(false));
+          mesh->computeNodeIdsAlg(nodeIdsInUse);
+        }
     }
-  int nbrOfNodesInUse=(int)std::count(nodeIdsInUse.begin(),nodeIdsInUse.end(),true);
+  int nbrOfNodesInUse((int)std::count(nodeIdsInUse.begin(),nodeIdsInUse.end(),true));
   if(nbrOfNodesInUse==nbOfNodes)
-    return 0;
-  MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret=DataArrayInt::New(); ret->alloc(nbOfNodes,1);
+    return 0;//no need to update _part_coords
+  MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret(DataArrayInt::New()); ret->alloc(nbOfNodes,1);
   std::transform(nodeIdsInUse.begin(),nodeIdsInUse.end(),ret->getPointer(),MEDLoaderAccVisit1());
-  MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret2=ret->invertArrayO2N2N2OBis(nbrOfNodesInUse);
-  MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> newCoords=coo->selectByTupleIdSafe(ret2->begin(),ret2->end());
+  MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret2(ret->invertArrayO2N2N2OBis(nbrOfNodesInUse));
+  MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> newCoords(coo->selectByTupleIdSafe(ret2->begin(),ret2->end()));
   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newFamCoords;
+  MEDCouplingAutoRefCountObjectPtr<DataArrayAsciiChar> newNameCoords;
   if((const DataArrayInt *)_fam_coords)
     newFamCoords=_fam_coords->selectByTupleIdSafe(ret2->begin(),ret2->end());
   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newNumCoords;
   if((const DataArrayInt *)_num_coords)
     newNumCoords=_num_coords->selectByTupleIdSafe(ret2->begin(),ret2->end());
-  _coords=newCoords; _fam_coords=newFamCoords; _num_coords=newNumCoords; _rev_num_coords=0;
+  if((const DataArrayAsciiChar *)_name_coords)
+    newNameCoords=static_cast<DataArrayAsciiChar *>(_name_coords->selectByTupleIdSafe(ret2->begin(),ret2->end()));
+  _coords=newCoords; _fam_coords=newFamCoords; _num_coords=newNumCoords; _name_coords=newNameCoords; _rev_num_coords=0;
   for(std::vector< MEDCouplingAutoRefCountObjectPtr<MEDFileUMeshSplitL1> >::iterator it=_ms.begin();it!=_ms.end();it++)
     {
       if((MEDFileUMeshSplitL1*)*it)
-        (*it)->renumberNodesInConn(ret->begin());
+        {
+          (*it)->renumberNodesInConn(ret->begin());
+          (*it)->setCoords(_coords);
+        }
+    }
+  // updates _part_coords
+  const PartDefinition *pc(_part_coords);
+  if(pc)
+    {
+      MEDCouplingAutoRefCountObjectPtr<PartDefinition> tmpPD(DataArrayPartDefinition::New(ret2));
+      _part_coords=tmpPD->composeWith(pc);
     }
   return ret.retn();
 }
 
 /*!
- * This method is here only to add a group on node.
- * MEDFileUMesh::setGroupsAtLevel with 1 in the first parameter.
+ * This method performs an extrusion along a path defined by \a m1D.
+ * \a this is expected to be a mesh with max mesh dimension equal to 2.
+ * \a m1D is expected to be a mesh with space dimesion equal to 3 and mesh dimension equal to 1.
+ * Mesh dimensions of returned mesh is incremented by one compared to thoose in \a this.
+ * This method scans all levels in \a this
+ * and put them in the returned mesh. All groups in \a this are also put in the returned mesh.
  *
- * \param [in] ids node ids and group name of the new group to add. The ids should be sorted and different each other (MED file norm).
+ * \param [in] m1D - the mesh defining the extrusion path.
+ * \param [in] policy - defines the policy of extrusion (see MEDCouplingUMesh::buildExtrudedMesh for more details)
+ * \return - a new reference on mesh (you have to deal with using decrRef). The returned mesh will have the same name than \a this.
+ *
+ * \sa MEDCouplingUMesh::buildExtrudedMesh
  */
-void MEDFileUMesh::addNodeGroup(const DataArrayInt *ids) throw(INTERP_KERNEL::Exception)
-{
-  const DataArrayDouble *coords=_coords;
-  if(!coords)
-    throw INTERP_KERNEL::Exception("MEDFileUMesh::addNodeGroup : no coords set !");
-  int nbOfNodes=coords->getNumberOfTuples();
-  if(!((DataArrayInt *)_fam_coords))
-    { _fam_coords=DataArrayInt::New(); _fam_coords->alloc(nbOfNodes,1); _fam_coords->fillWithZero(); }
-  //
-  addGroupUnderground(ids,_fam_coords);
-}
-
-void MEDFileUMesh::addGroup(int meshDimRelToMaxExt, const DataArrayInt *ids) throw(INTERP_KERNEL::Exception)
-{
-  std::vector<int> levs=getNonEmptyLevelsExt();
-  if(std::find(levs.begin(),levs.end(),meshDimRelToMaxExt)==levs.end())
-    { 
-      std::ostringstream oss; oss << "MEDFileUMesh::addGroup : level " << meshDimRelToMaxExt << " not available ! Should be in ";
-      std::copy(levs.begin(),levs.end(),std::ostream_iterator<int>(oss," ")); oss << " !"; throw INTERP_KERNEL::Exception(oss.str().c_str());
+MEDFileUMesh *MEDFileUMesh::buildExtrudedMesh(const MEDCouplingUMesh *m1D, int policy) const
+{
+  if(getMeshDimension()!=2)
+    throw INTERP_KERNEL::Exception("MEDFileUMesh::buildExtrudedMesh : this is expected to be with mesh dimension equal to 2 !");
+  MEDCouplingAutoRefCountObjectPtr<MEDFileUMesh> ret(MEDFileUMesh::New());
+  m1D->checkCoherency();
+  if(m1D->getMeshDimension()!=1)
+    throw INTERP_KERNEL::Exception("MEDFileUMesh::buildExtrudedMesh : input mesh must have a mesh dimension equal to one !");
+  int nbRep(m1D->getNumberOfCells());
+  std::vector<int> levs(getNonEmptyLevels());
+  std::vector<std::string> grps(getGroupsNames());
+  std::vector< MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> > zeList;
+  DataArrayDouble *coords(0);
+  std::size_t nbOfLevsOut(levs.size()+1);
+  std::vector< MEDCouplingAutoRefCountObjectPtr<DataArrayInt> > o2ns(nbOfLevsOut);
+  for(std::vector<int>::const_iterator lev=levs.begin();lev!=levs.end();lev++)
+    {
+      MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> item(getMeshAtLevel(*lev));
+      item=item->clone(false);
+      item->changeSpaceDimension(3+(*lev),0.);//no problem non const but change DataArrayDouble for coordinates do not alter data
+      MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> tmp(static_cast<MEDCouplingUMesh *>(m1D->deepCpy()));
+      tmp->changeSpaceDimension(3+(*lev),0.);
+      MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> elt(item->buildExtrudedMesh(tmp,policy));
+      zeList.push_back(elt);
+      if(*lev==0)
+        coords=elt->getCoords();
     }
-  if(meshDimRelToMaxExt==1)
-    { addNodeGroup(ids); return ; }
-  MEDFileUMeshSplitL1 *lev=getMeshAtLevSafe(meshDimRelToMaxExt);
-  DataArrayInt *fam=lev->getOrCreateAndGetFamilyField();
-  addGroupUnderground(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 NULL (no check of that will be performed)
- */
-void MEDFileUMesh::addGroupUnderground(const DataArrayInt *ids, DataArrayInt *famArr) throw(INTERP_KERNEL::Exception)
-{
-  if(!ids)
-    throw INTERP_KERNEL::Exception("MEDFileUMesh::addGroup : NULL pointer in input !");
-  std::string grpName(ids->getName());
-  if(grpName.empty())
-    throw INTERP_KERNEL::Exception("MEDFileUMesh::addGroup : empty group name ! MED file format do not accept empty group name !");
-  ids->checkStrictlyMonotonic(true);
-  famArr->incrRef(); MEDCouplingAutoRefCountObjectPtr<DataArrayInt> famArrTmp(famArr);
-  std::vector<std::string> grpsNames=getGroupsNames();
-  if(std::find(grpsNames.begin(),grpsNames.end(),grpName)!=grpsNames.end())
+  if(!coords)
+    throw INTERP_KERNEL::Exception("MEDFileUMesh::buildExtrudedMesh : internal error !");
+  for(std::vector< MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> >::iterator it=zeList.begin();it!=zeList.end();it++)
     {
-      std::ostringstream oss; oss << "MEDFileUMesh::addGroup : Group with name \"" << grpName << "\" already exists ! Destroy it before calling this method !";
-      throw INTERP_KERNEL::Exception(oss.str().c_str());
+      (*it)->setName(getName());
+      (*it)->setCoords(coords);
     }
-  std::list< MEDCouplingAutoRefCountObjectPtr<DataArrayInt> > allFamIds=getAllNonNullFamilyIds();
-  allFamIds.erase(std::find(allFamIds.begin(),allFamIds.end(),famArrTmp));
-  MEDCouplingAutoRefCountObjectPtr<DataArrayInt> famIds=famArr->selectByTupleIdSafe(ids->begin(),ids->end());
-  std::set<int> diffFamIds=famIds->getDifferentValues();
-  std::vector<int> familyIds;
-  std::vector< MEDCouplingAutoRefCountObjectPtr<DataArrayInt> > idsPerfamiliyIds;
-  int maxVal=getTheMaxFamilyId()+1;
-  std::map<std::string,int> families(_families);
-  std::map<std::string, std::vector<std::string> > groups(_groups);
-  std::vector<std::string> fams;
-  bool created(false);
-  for(std::set<int>::const_iterator famId=diffFamIds.begin();famId!=diffFamIds.end();famId++)
+  for(std::size_t ii=0;ii!=zeList.size();ii++)
     {
-      MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ids2Tmp=famIds->getIdsEqual(*famId);
-      MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ids2=ids->selectByTupleId(ids2Tmp->begin(),ids2Tmp->end());
-      MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ids1=famArr->getIdsEqual(*famId);
-      MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret0(ids1->buildSubstractionOptimized(ids2));
-      if(ret0->empty())
+      int lev(levs[ii]);
+      MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> elt(zeList[ii]);
+      if(lev<=-1)
         {
-          bool isFamPresent=false;
-          for(std::list< MEDCouplingAutoRefCountObjectPtr<DataArrayInt> >::const_iterator itl=allFamIds.begin();itl!=allFamIds.end() && !isFamPresent;itl++)
-            isFamPresent=(*itl)->presenceOfValue(*famId);
-          if(!isFamPresent)
-            { familyIds.push_back(*famId); idsPerfamiliyIds.push_back(ret0); fams.push_back(FindOrCreateAndGiveFamilyWithId(families,*famId,created)); } // adding *famId in grp
-          else
+          MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> elt1(getMeshAtLevel(lev+1));
+          MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> elt2(elt1->clone(false));
+          MEDCouplingAutoRefCountObjectPtr<DataArrayInt> tmp(elt2->getNodalConnectivity()->deepCpy());
+          elt2->setConnectivity(tmp,elt2->getNodalConnectivityIndex());
+          elt2->shiftNodeNumbersInConn(nbRep*elt1->getNumberOfNodes());
+          elt1->setCoords(elt->getCoords()); elt2->setCoords(elt->getCoords());
+          std::vector<const MEDCouplingUMesh *> elts(3);
+          elts[0]=elt; elts[1]=elt1; elts[2]=elt2;
+          elt=MEDCouplingUMesh::MergeUMeshesOnSameCoords(elts);
+          elt->setName(getName());
+        }
+      //
+      o2ns[ii]=elt->sortCellsInMEDFileFrmt();
+      ret->setMeshAtLevel(lev,elt);
+    }
+  MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> endLev(getMeshAtLevel(levs.back())),endLev2;
+  endLev=endLev->clone(false); endLev->setCoords(coords);
+  MEDCouplingAutoRefCountObjectPtr<DataArrayInt> tmp(endLev->getNodalConnectivity()->deepCpy());
+  endLev2=endLev->clone(false); endLev2->setConnectivity(tmp,endLev->getNodalConnectivityIndex());
+  endLev2->shiftNodeNumbersInConn(nbRep*getNumberOfNodes());
+  endLev=MEDCouplingUMesh::MergeUMeshesOnSameCoords(endLev,endLev2);
+  o2ns[levs.size()]=endLev->sortCellsInMEDFileFrmt();
+  endLev->setName(getName());
+  ret->setMeshAtLevel(levs.back()-1,endLev);
+  //
+  for(std::size_t ii=0;ii!=zeList.size();ii++)
+    {
+      int lev(levs[ii]);
+      std::vector< MEDCouplingAutoRefCountObjectPtr<DataArrayInt> > outGrps;
+      std::vector< const DataArrayInt * > outGrps2;
+      if(lev<=-1)
+        {
+          for(std::vector<std::string>::const_iterator grp=grps.begin();grp!=grps.end();grp++)
             {
-              familyIds.push_back(maxVal); idsPerfamiliyIds.push_back(ids2); std::string locFamName=FindOrCreateAndGiveFamilyWithId(families,maxVal,created);
-              fams.push_back(locFamName);
-              if(existsFamily(*famId))
+              MEDCouplingAutoRefCountObjectPtr<DataArrayInt> grpArr(getGroupArr(lev+1,*grp));
+              if(!grpArr->empty())
                 {
-                  std::string locFamName2=getFamilyNameGivenId(*famId); std::vector<std::string> v(2); v[0]=locFamName2; v[1]=locFamName;
-                  ChangeAllGroupsContainingFamily(groups,getFamilyNameGivenId(*famId).c_str(),v);
+                  MEDCouplingAutoRefCountObjectPtr<DataArrayInt> grpArr1(grpArr->deepCpy()),grpArr2(grpArr->deepCpy());
+                  int offset0(zeList[ii]->getNumberOfCells());
+                  int offset1(offset0+getNumberOfCellsAtLevel(lev+1));
+                  grpArr1->applyLin(1,offset0); grpArr2->applyLin(1,offset1);
+                  std::ostringstream oss; oss << grpArr2->getName() << "_top";
+                  grpArr2->setName(oss.str());
+                  grpArr1->transformWithIndArr(o2ns[ii]->begin(),o2ns[ii]->end());
+                  grpArr2->transformWithIndArr(o2ns[ii]->begin(),o2ns[ii]->end());
+                  outGrps.push_back(grpArr1); outGrps.push_back(grpArr2);
+                  outGrps2.push_back(grpArr1); outGrps2.push_back(grpArr2);
                 }
-              maxVal++;
-            } // modifying all other groups on *famId to lie on maxVal and lie the grp on maxVal
+            }
         }
-      else
+      //
+      for(std::vector<std::string>::const_iterator grp=grps.begin();grp!=grps.end();grp++)
         {
-          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);
-          if(existsFamily(*famId))
+          MEDCouplingAutoRefCountObjectPtr<DataArrayInt> grpArr(getGroupArr(lev,*grp));
+          if(!grpArr->empty())
             {
-              std::string n1(FindOrCreateAndGiveFamilyWithId(families,maxVal,created)); std::vector<std::string> v(2); v[0]=n1; v[1]=n2;
-              ChangeAllGroupsContainingFamily(groups,getFamilyNameGivenId(*famId).c_str(),v);
+              int nbCellsB4Extrusion(getNumberOfCellsAtLevel(lev));
+              std::vector< MEDCouplingAutoRefCountObjectPtr<DataArrayInt> > grpArrs(nbRep);
+              std::vector< const DataArrayInt *> grpArrs2(nbRep);
+              for(int iii=0;iii<nbRep;iii++)
+                {
+                  grpArrs[iii]=grpArr->deepCpy(); grpArrs[iii]->applyLin(1,iii*nbCellsB4Extrusion);
+                  grpArrs2[iii]=grpArrs[iii];
+                }
+              MEDCouplingAutoRefCountObjectPtr<DataArrayInt> grpArrExt(DataArrayInt::Aggregate(grpArrs2));
+              grpArrExt->transformWithIndArr(o2ns[ii]->begin(),o2ns[ii]->end());
+              std::ostringstream grpName; grpName << *grp << "_extruded";
+              grpArrExt->setName(grpName.str());
+              outGrps.push_back(grpArrExt);
+              outGrps2.push_back(grpArrExt);
             }
-          maxVal+=2;
         }
-    }
-  for(std::size_t i=0;i<familyIds.size();i++)
-    {
-      DataArrayInt *da=idsPerfamiliyIds[i];
-      famArr->setPartOfValuesSimple3(familyIds[i],da->begin(),da->end(),0,1,1);
-    }
-  _families=families;
-  _groups=groups;
-  _groups[grpName]=fams;
-}
-
-void MEDFileUMesh::setFamilyNameAttachedOnId(int id, const std::string& newFamName) throw(INTERP_KERNEL::Exception)
-{
-  std::string oldName=getFamilyNameGivenId(id);
-  _families.erase(oldName);
-  _families[newFamName]=id;
+      ret->setGroupsAtLevel(lev,outGrps2);
+    }
+  std::vector< MEDCouplingAutoRefCountObjectPtr<DataArrayInt> > outGrps;
+  std::vector< const DataArrayInt * > outGrps2;
+  for(std::vector<std::string>::const_iterator grp=grps.begin();grp!=grps.end();grp++)
+    {
+      MEDCouplingAutoRefCountObjectPtr<DataArrayInt> grpArr1(getGroupArr(levs.back(),*grp));
+      if(grpArr1->empty())
+        continue;
+      MEDCouplingAutoRefCountObjectPtr<DataArrayInt> grpArr2(grpArr1->deepCpy());
+      std::ostringstream grpName; grpName << *grp << "_top";
+      grpArr2->setName(grpName.str());
+      grpArr2->applyLin(1,getNumberOfCellsAtLevel(levs.back()));
+      outGrps.push_back(grpArr1); outGrps.push_back(grpArr2);
+      outGrps2.push_back(grpArr1); outGrps2.push_back(grpArr2);
+    }
+  ret->setGroupsAtLevel(levs.back()-1,outGrps2);
+  return ret.retn();
 }
 
-void MEDFileUMesh::removeMeshAtLevel(int meshDimRelToMax) throw(INTERP_KERNEL::Exception)
+/*!
+ * This method converts all linear cells in \a this into quadratic cells (following the \a conversionType policy).
+ * All the cells converted are put in the returned instance. This method applies all the groups and families in \a this to returned instance.
+ * Groups on nodes and families on nodes are copied directly to the returned instance without transformation.
+ *
+ * \param [in] conversionType - conversionType specifies the type of conversion expected. Only 0 (default) and 1 are supported presently. 0 those that creates the 'most' simple
+ *             corresponding quadratic cells. 1 is those creating the 'most' complex.
+ * \param [in] eps - detection threshold for coordinates.
+ * \return A new instance that is the result of the conversion. The caller has the ownership of this returned instance.
+ *
+ * \sa MEDCouplingUMesh::convertLinearCellsToQuadratic , quadraticToLinear
+ */
+MEDFileUMesh *MEDFileUMesh::linearToQuadratic(int conversionType, double eps) const
 {
-  std::vector<int> levSet=getNonEmptyLevels();
-  std::vector<int>::const_iterator it=std::find(levSet.begin(),levSet.end(),meshDimRelToMax);
-  if(it==levSet.end())
-    throw INTERP_KERNEL::Exception("MEDFileUMesh::removeMeshAtLevel : the requested level is not existing !");
-  int pos=(-meshDimRelToMax);
-  _ms[pos]=0;
+  MEDCouplingAutoRefCountObjectPtr<MEDFileUMesh> ret(MEDFileUMesh::New());
+  int initialNbNodes(getNumberOfNodes());
+  MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> m0Tmp(getMeshAtLevel(0));
+  MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> m0(dynamic_cast<MEDCouplingUMesh *>(m0Tmp->deepCpy()));
+  {
+    MEDCouplingAutoRefCountObjectPtr<DataArrayInt> notUsed(m0->convertLinearCellsToQuadratic(conversionType));
+  }
+  DataArrayDouble *zeCoords(m0->getCoords());
+  ret->setMeshAtLevel(0,m0);
+  std::vector<int> levs(getNonEmptyLevels());
+  const DataArrayInt *famField(getFamilyFieldAtLevel(0));
+  if(famField)
+    {
+      MEDCouplingAutoRefCountObjectPtr<DataArrayInt> famFieldCpy(famField->deepCpy());
+      ret->setFamilyFieldArr(0,famFieldCpy);
+    }
+  famField=getFamilyFieldAtLevel(1);
+  if(famField)
+    {
+      MEDCouplingAutoRefCountObjectPtr<DataArrayInt> fam(DataArrayInt::New()); fam->alloc(zeCoords->getNumberOfTuples(),1);
+      fam->fillWithZero();
+      fam->setPartOfValues1(famField,0,initialNbNodes,1,0,1,1);
+      ret->setFamilyFieldArr(1,fam);
+    }
+  ret->copyFamGrpMapsFrom(*this);
+  MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> partZeCoords(zeCoords->selectByTupleId2(initialNbNodes,zeCoords->getNumberOfTuples(),1));
+  for(std::vector<int>::const_iterator lev=levs.begin();lev!=levs.end();lev++)
+    {
+      if(*lev==0)
+        continue;
+      MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> m1Tmp(getMeshAtLevel(*lev));
+      MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> m1(dynamic_cast<MEDCouplingUMesh *>(m1Tmp->deepCpy()));
+      {
+        MEDCouplingAutoRefCountObjectPtr<DataArrayInt> notUsed(m1->convertLinearCellsToQuadratic(conversionType));
+      }
+      MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> m1Coords(m1->getCoords()->selectByTupleId2(initialNbNodes,m1->getNumberOfNodes(),1));
+      DataArrayInt *b(0);
+      bool a(partZeCoords->areIncludedInMe(m1Coords,eps,b));
+      MEDCouplingAutoRefCountObjectPtr<DataArrayInt> bSafe(b);
+      if(!a)
+        {
+          std::ostringstream oss; oss << "MEDFileUMesh::linearCellsToQuadratic : for level " << *lev << " problem to identify nodes generated !";
+          throw INTERP_KERNEL::Exception(oss.str().c_str());
+        }
+      b->applyLin(1,initialNbNodes);
+      MEDCouplingAutoRefCountObjectPtr<DataArrayInt> l0(DataArrayInt::New()); l0->alloc(initialNbNodes,1); l0->iota();
+      std::vector<const DataArrayInt *> v(2); v[0]=l0; v[1]=b;
+      MEDCouplingAutoRefCountObjectPtr<DataArrayInt> renum(DataArrayInt::Aggregate(v));
+      m1->renumberNodesInConn(renum->begin());
+      m1->setCoords(zeCoords);
+      ret->setMeshAtLevel(*lev,m1);
+      famField=getFamilyFieldAtLevel(*lev);
+      if(famField)
+        {
+          MEDCouplingAutoRefCountObjectPtr<DataArrayInt> famFieldCpy(famField->deepCpy());
+          ret->setFamilyFieldArr(*lev,famFieldCpy);
+        }
+    }
+  return ret.retn();
 }
 
-void MEDFileUMesh::setMeshAtLevel(int meshDimRelToMax, MEDCouplingUMesh *m, bool newOrOld) throw(INTERP_KERNEL::Exception)
-{
-  setMeshAtLevelGen(meshDimRelToMax,m,newOrOld);
+/*!
+ * This method converts all quadratic cells in \a this into linear cells.
+ * All the cells converted are put in the returned instance. This method applies all the groups and families in \a this to returned instance.
+ * Groups on nodes and families on nodes are copied directly to the returned instance without transformation.
+ *
+ * \param [in] eps - detection threshold for coordinates.
+ * \return A new instance that is the result of the conversion. The caller has the ownership of this returned instance.
+ *
+ * \sa MEDCouplingUMesh::convertLinearCellsToQuadratic , linearToQuadratic
+ */
+MEDFileUMesh *MEDFileUMesh::quadraticToLinear(double eps) const
+{
+  MEDCouplingAutoRefCountObjectPtr<MEDFileUMesh> ret(MEDFileUMesh::New());
+  MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> m0Tmp(getMeshAtLevel(0));
+  MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> m0(dynamic_cast<MEDCouplingUMesh *>(m0Tmp->deepCpy()));
+  m0->convertQuadraticCellsToLinear();
+  m0->zipCoords();
+  DataArrayDouble *zeCoords(m0->getCoords());
+  ret->setMeshAtLevel(0,m0);
+  std::vector<int> levs(getNonEmptyLevels());
+  const DataArrayInt *famField(getFamilyFieldAtLevel(0));
+  if(famField)
+    {
+      MEDCouplingAutoRefCountObjectPtr<DataArrayInt> famFieldCpy(famField->deepCpy());
+      ret->setFamilyFieldArr(0,famFieldCpy);
+    }
+  famField=getFamilyFieldAtLevel(1);
+  if(famField)
+    {
+      MEDCouplingAutoRefCountObjectPtr<DataArrayInt> fam(famField->selectByTupleId2(0,zeCoords->getNumberOfTuples(),1));
+      ret->setFamilyFieldArr(1,fam);
+    }
+  ret->copyFamGrpMapsFrom(*this);
+  for(std::vector<int>::const_iterator lev=levs.begin();lev!=levs.end();lev++)
+    {
+      if(*lev==0)
+        continue;
+      MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> m1Tmp(getMeshAtLevel(*lev));
+      MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> m1(dynamic_cast<MEDCouplingUMesh *>(m1Tmp->deepCpy()));
+      m1->convertQuadraticCellsToLinear();
+      m1->zipCoords();
+      DataArrayInt *b(0);
+      bool a(zeCoords->areIncludedInMe(m1->getCoords(),eps,b));
+      MEDCouplingAutoRefCountObjectPtr<DataArrayInt> bSafe(b);
+      if(!a)
+        {
+          std::ostringstream oss; oss << "MEDFileUMesh::quadraticToLinear : for level " << *lev << " problem to identify nodes generated !";
+          throw INTERP_KERNEL::Exception(oss.str().c_str());
+        }
+      m1->renumberNodesInConn(b->begin());
+      m1->setCoords(zeCoords);
+      ret->setMeshAtLevel(*lev,m1);
+      famField=getFamilyFieldAtLevel(*lev);
+      if(famField)
+        {
+          MEDCouplingAutoRefCountObjectPtr<DataArrayInt> famFieldCpy(famField->deepCpy());
+          ret->setFamilyFieldArr(*lev,famFieldCpy);
+        }
+    }
+  return ret.retn();
 }
 
-void MEDFileUMesh::setMeshAtLevelGen(int meshDimRelToMax, MEDCouplingUMesh *m, bool newOrOld) throw(INTERP_KERNEL::Exception)
+void MEDFileUMesh::serialize(std::vector<double>& tinyDouble, std::vector<int>& tinyInt, std::vector<std::string>& tinyStr, std::vector< MEDCouplingAutoRefCountObjectPtr<DataArrayInt> >& bigArraysI, MEDCouplingAutoRefCountObjectPtr<DataArrayDouble>& bigArrayD)
 {
-  dealWithTinyInfo(m);
-  std::vector<int> levSet=getNonEmptyLevels();
-  if(std::find(levSet.begin(),levSet.end(),meshDimRelToMax)==levSet.end())
+  clearNonDiscrAttributes();
+  forceComputationOfParts();
+  tinyDouble.clear(); tinyInt.clear(); tinyStr.clear(); bigArraysI.clear(); bigArrayD=0;
+  std::vector<int> layer0;
+  layer0.push_back(_order); //0 i
+  layer0.push_back(_iteration);//1 i
+  layer0.push_back(getSpaceDimension());//2 i
+  tinyDouble.push_back(_time);//0 d
+  tinyStr.push_back(_name);//0 s
+  tinyStr.push_back(_desc_name);//1 s
+  for(int i=0;i<getSpaceDimension();i++)
+    tinyStr.push_back(_coords->getInfoOnComponent(i));
+  layer0.push_back((int)_families.size());//3 i <- key info aa layer#0
+  for(std::map<std::string,int>::const_iterator it=_families.begin();it!=_families.end();it++)
     {
-      if((DataArrayDouble *)_coords==0)
+      tinyStr.push_back((*it).first);
+      layer0.push_back((*it).second);
+    }
+  layer0.push_back((int)_groups.size());//3+aa i <- key info bb layer#0
+  for(std::map<std::string, std::vector<std::string> >::const_iterator it0=_groups.begin();it0!=_groups.end();it0++)
+    {
+      layer0.push_back((int)(*it0).second.size());
+      tinyStr.push_back((*it0).first);
+      for(std::vector<std::string>::const_iterator it1=((*it0).second).begin();it1!=((*it0).second).end();it1++)
+        tinyStr.push_back(*it1);
+    }
+  // sizeof(layer0)==3+aa+1+bb layer#0
+  bigArrayD=_coords;// 0 bd
+  bigArraysI.push_back(_fam_coords);// 0 bi
+  bigArraysI.push_back(_num_coords);// 1 bi
+  const PartDefinition *pd(_part_coords);
+  if(!pd)
+    layer0.push_back(-1);
+  else
+    {
+      std::vector<int> tmp0;
+      pd->serialize(tmp0,bigArraysI);
+      tinyInt.push_back(tmp0.size());
+      tinyInt.insert(tinyInt.end(),tmp0.begin(),tmp0.end());
+    }
+  //
+  std::vector<int> layer1;
+  std::vector<int> levs(getNonEmptyLevels());
+  layer1.push_back((int)levs.size());// 0 i <- key
+  layer1.insert(layer1.end(),levs.begin(),levs.end());
+  for(std::vector<int>::const_iterator it=levs.begin();it!=levs.end();it++)
+    {
+      const MEDFileUMeshSplitL1 *lev(getMeshAtLevSafe(*it));
+      lev->serialize(layer1,bigArraysI);
+    }
+  // put layers all together.
+  tinyInt.push_back(layer0.size());
+  tinyInt.insert(tinyInt.end(),layer0.begin(),layer0.end());
+  tinyInt.push_back(layer1.size());
+  tinyInt.insert(tinyInt.end(),layer1.begin(),layer1.end());
+}
+
+void MEDFileUMesh::unserialize(std::vector<double>& tinyDouble, std::vector<int>& tinyInt, std::vector<std::string>& tinyStr,
+                               std::vector< MEDCouplingAutoRefCountObjectPtr<DataArrayInt> >& bigArraysI, MEDCouplingAutoRefCountObjectPtr<DataArrayDouble>& bigArrayD)
+{
+  int sz0(tinyInt[0]);
+  std::vector<int> layer0(tinyInt.begin()+1,tinyInt.begin()+1+sz0);
+  int sz1(tinyInt[sz0+1]);
+  std::vector<int> layer1(tinyInt.begin()+2+sz0,tinyInt.begin()+2+sz0+sz1);
+  //
+  std::reverse(layer0.begin(),layer0.end());
+  std::reverse(layer1.begin(),layer1.end());
+  std::reverse(tinyDouble.begin(),tinyDouble.end());
+  std::reverse(tinyStr.begin(),tinyStr.end());
+  std::reverse(bigArraysI.begin(),bigArraysI.end());
+  //
+  _order=layer0.back(); layer0.pop_back();
+  _iteration=layer0.back(); layer0.pop_back();
+  int spaceDim(layer0.back()); layer0.pop_back();
+  _time=tinyDouble.back(); tinyDouble.pop_back();
+  _name=tinyStr.back(); tinyStr.pop_back();
+  _desc_name=tinyStr.back(); tinyStr.pop_back();
+  _coords=bigArrayD; _coords->rearrange(spaceDim);
+  for(int i=0;i<spaceDim;i++)
+    {
+      _coords->setInfoOnComponent(i,tinyStr.back());
+      tinyStr.pop_back();
+    }
+  int nbOfFams(layer0.back()); layer0.pop_back();
+  _families.clear();
+  for(int i=0;i<nbOfFams;i++)
+    {
+      _families[tinyStr.back()]=layer0.back();
+      tinyStr.pop_back(); layer0.pop_back();
+    }
+  int nbGroups(layer0.back()); layer0.pop_back();
+  _groups.clear();
+  for(int i=0;i<nbGroups;i++)
+    {
+      std::string grpName(tinyStr.back()); tinyStr.pop_back();
+      int nbOfFamsOnGrp(layer0.back()); layer0.pop_back();
+      std::vector<std::string> fams(nbOfFamsOnGrp);
+      for(int j=0;j<nbOfFamsOnGrp;j++)
+        {
+          fams[j]=tinyStr.back(); tinyStr.pop_back();
+        }
+      _groups[grpName]=fams;
+    }
+  _fam_coords=bigArraysI.back(); bigArraysI.pop_back();
+  _num_coords=bigArraysI.back(); bigArraysI.pop_back();
+  _part_coords=0;
+  int isPd(layer0.back()); layer0.pop_back();
+  if(isPd!=-1)
+    {
+      std::vector<int> tmp0(layer0.begin(),layer0.begin()+isPd);
+      layer0.erase(layer0.begin(),layer0.begin()+isPd);
+      _part_coords=PartDefinition::Unserialize(tmp0,bigArraysI);
+    }
+  if(!layer0.empty())
+    throw INTERP_KERNEL::Exception("MEDFileUMesh::unserialize : something wrong during unserialization #1 !");
+  //
+  int nbLevs(layer1.back()); layer1.pop_back();
+  std::vector<int> levs(layer1.rbegin(),layer1.rbegin()+nbLevs); layer1.erase(layer1.end()-nbLevs,layer1.end());
+  _ms.clear();
+  int maxLev(-(*std::min_element(levs.begin(),levs.end())));
+  _ms.resize(maxLev+1);
+  for(int i=0;i<nbLevs;i++)
+    {
+      int lev(levs[i]);
+      int pos(-lev);
+      _ms[pos]=MEDFileUMeshSplitL1::Unserialize(_name,_coords,layer1,bigArraysI);
+    }
+}
+
+/*!
+ * Adds a group of nodes 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).
+ *
+ *  \warning this method can alter default "FAMILLE_ZERO" family.
+ *  For users sensitive to this a call to MEDFileMesh::rearrangeFamilies will be necessary after addGroup session.
+ *
+ *  \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::addNodeGroup(const DataArrayInt *ids)
+{
+  const DataArrayDouble *coords(_coords);
+  if(!coords)
+    throw INTERP_KERNEL::Exception("MEDFileUMesh::addNodeGroup : no coords set !");
+  int nbOfNodes(coords->getNumberOfTuples());
+  if(!((DataArrayInt *)_fam_coords))
+    { _fam_coords=DataArrayInt::New(); _fam_coords->alloc(nbOfNodes,1); _fam_coords->fillWithZero(); }
+  //
+  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).
+ *
+ * \warning this method can alter default "FAMILLE_ZERO" family.
+ * For users sensitive to this a call to MEDFileMesh::rearrangeFamilies will be necessary after addGroup session.
+ *
+ *  \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)
+{
+  std::vector<int> levs(getNonEmptyLevelsExt());
+  if(std::find(levs.begin(),levs.end(),meshDimRelToMaxExt)==levs.end())
+    { 
+      std::ostringstream oss; oss << "MEDFileUMesh::addGroup : level " << meshDimRelToMaxExt << " not available ! Should be in ";
+      std::copy(levs.begin(),levs.end(),std::ostream_iterator<int>(oss," ")); oss << " !"; throw INTERP_KERNEL::Exception(oss.str().c_str());
+    }
+  if(meshDimRelToMaxExt==1)
+    { addNodeGroup(ids); return ; }
+  MEDFileUMeshSplitL1 *lev(getMeshAtLevSafe(meshDimRelToMaxExt));
+  DataArrayInt *fam(lev->getOrCreateAndGetFamilyField());
+  addGroupUnderground(false,ids,fam);
+}
+
+/*!
+ * Changes a name of a family specified by its id.
+ *  \param [in] id - the id of the family of interest.
+ *  \param [in] newFamName - the new family name.
+ *  \throw If no family with the given \a id exists.
+ */
+void MEDFileUMesh::setFamilyNameAttachedOnId(int id, const std::string& newFamName)
+{
+  std::string oldName=getFamilyNameGivenId(id);
+  _families.erase(oldName);
+  _families[newFamName]=id;
+}
+
+/*!
+ * Removes a mesh of a given dimension.
+ *  \param [in] meshDimRelToMax - the relative dimension of interest.
+ *  \throw If there is no mesh at level \a meshDimRelToMax in \a this mesh.
+ */
+void MEDFileUMesh::removeMeshAtLevel(int meshDimRelToMax)
+{
+  std::vector<int> levSet=getNonEmptyLevels();
+  std::vector<int>::const_iterator it=std::find(levSet.begin(),levSet.end(),meshDimRelToMax);
+  if(it==levSet.end())
+    throw INTERP_KERNEL::Exception("MEDFileUMesh::removeMeshAtLevel : the requested level is not existing !");
+  int pos=(-meshDimRelToMax);
+  _ms[pos]=0;
+}
+
+/*!
+ * Sets a new MEDCoupling1GTUMesh at a given level in \a this mesh.
+ *  \param [in] meshDimRelToMax - a relative level to set the mesh at.
+ *  \param [in] m - the new mesh to set.
+ *  \throw If the name or the description of \a this mesh and \a m are not empty and are
+ *         different. 
+ *  \throw If the node coordinates array is set \a this in mesh and \a m refers to
+ *         another node coordinates array.
+ *  \throw If the mesh dimension of \a m does not correspond to \a meshDimRelToMax or
+ *         to the existing meshes of other levels of \a this mesh.
+ */
+void MEDFileUMesh::setMeshAtLevel(int meshDimRelToMax, MEDCoupling1GTUMesh *m)
+{
+  MEDCouplingAutoRefCountObjectPtr<MEDFileUMeshSplitL1> elt(new MEDFileUMeshSplitL1(m));
+  checkAndGiveEntryInSplitL1(meshDimRelToMax,m)=elt;
+}
+
+/*!
+ * Sets a new MEDCouplingUMesh at a given level in \a this mesh.
+ *  \param [in] meshDimRelToMax - a relative level to set the mesh at.
+ *  \param [in] m - the new mesh to set.
+ *  \param [in] newOrOld - if \c true, cells in \a m are sorted by type to be ready for 
+ *         writing \a this mesh in a MED file.
+ *  \throw If the name or the description of \a this mesh and \a m are not empty and are
+ *         different. 
+ *  \throw If the node coordinates array is set \a this in mesh and \a m refers to
+ *         another node coordinates array.
+ *  \throw If the mesh dimension of \a m does not correspond to \a meshDimRelToMax or
+ *         to the existing meshes of other levels of \a this mesh.
+ */
+void MEDFileUMesh::setMeshAtLevel(int meshDimRelToMax, MEDCouplingUMesh *m, bool newOrOld)
+{
+  MEDCouplingAutoRefCountObjectPtr<MEDFileUMeshSplitL1> elt(new MEDFileUMeshSplitL1(m,newOrOld));
+  checkAndGiveEntryInSplitL1(meshDimRelToMax,m)=elt;
+}
+
+MEDCouplingAutoRefCountObjectPtr<MEDFileUMeshSplitL1>& MEDFileUMesh::checkAndGiveEntryInSplitL1(int meshDimRelToMax, MEDCouplingPointSet *m)
+{
+  dealWithTinyInfo(m);
+  std::vector<int> levSet=getNonEmptyLevels();
+  if(std::find(levSet.begin(),levSet.end(),meshDimRelToMax)==levSet.end())
+    {
+      if((DataArrayDouble *)_coords==0)
         {
           DataArrayDouble *c=m->getCoords();
           if(c)
@@ -2571,13 +4371,73 @@ void MEDFileUMesh::setMeshAtLevelGen(int meshDimRelToMax, MEDCouplingUMesh *m, b
       if(sz>=(int)_ms.size())
         _ms.resize(sz);
       checkMeshDimCoherency(m->getMeshDimension(),meshDimRelToMax);
-      _ms[sz-1]=new MEDFileUMeshSplitL1(m,newOrOld);
+      return _ms[sz-1];
     }
   else
-    _ms[-meshDimRelToMax]=new MEDFileUMeshSplitL1(m,newOrOld);
+    return _ms[-meshDimRelToMax];
+}
+
+/*!
+ * 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)
+{
+  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());
+      setMeshAtLevel(mdim-zeDim,const_cast<MEDCouplingUMesh *>(*it),renum);
+    }
+  setName(name);
 }
 
-void MEDFileUMesh::setGroupsFromScratch(int meshDimRelToMax, const std::vector<const MEDCouplingUMesh *>& ms) throw(INTERP_KERNEL::Exception)
+/*!
+ * 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.
+ * The given meshes must share the same node coordinates array.
+ *  \param [in] meshDimRelToMax - the relative dimension to create the mesh and groups at.
+ *  \param [in] ms - the sequence of meshes. Each mesh in \a ms represents a group to
+ *          create in \a this mesh.
+ *  \throw If \a ms is empty.
+ *  \throw If dimension of meshes in \a ms does not correspond to \a meshDimRelToMax or
+ *         to the existing meshes of other levels of \a this mesh.
+ *  \throw If the meshes in \a ms do not share the same node coordinates array.
+ *  \throw If the node coordinates array of \a this mesh (if any) is not the same as that
+ *         of the given meshes.
+ *  \throw If \a ms[ i ] is not well defined (MEDCouplingUMesh::checkCoherency()).
+ *  \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, bool renum)
 {
   if(ms.empty())
     throw INTERP_KERNEL::Exception("MEDFileUMesh::setGroupsFromScratch : expecting a non empty vector !");
@@ -2597,12 +4457,31 @@ 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);
 }
 
-void MEDFileUMesh::setGroupsOnSetMesh(int meshDimRelToMax, const std::vector<const MEDCouplingUMesh *>& ms, bool renum) throw(INTERP_KERNEL::Exception)
+/*!
+ * Creates groups at a given level in \a this mesh from a sequence of
+ * meshes each representing a group.
+ * The given meshes must share the same node coordinates array.
+ *  \param [in] meshDimRelToMax - the relative dimension to create the groups at.
+ *  \param [in] ms - the sequence of meshes. Each mesh in \a ms represents a group to
+ *         create in \a this mesh.
+ *  \param [in] renum - if \c true, then the optional numbers of entities are taken into
+ *         account. 
+ *  \throw If \a ms is empty.
+ *  \throw If dimension of meshes in \a ms does not correspond to \a meshDimRelToMax or
+ *         to the existing meshes of other levels of \a this mesh.
+ *  \throw If the meshes in \a ms do not share the same node coordinates array.
+ *  \throw If the node coordinates array of \a this mesh (if any) is not the same as that
+ *         of the given meshes.
+ *  \throw If \a ms[ i ] is not well defined (MEDCouplingUMesh::checkCoherency()).
+ *  \throw If names of some meshes in \a ms are equal.
+ *  \throw If \a ms includes a mesh with an empty name.
+ */
+void MEDFileUMesh::setGroupsOnSetMesh(int meshDimRelToMax, const std::vector<const MEDCouplingUMesh *>& ms, bool renum)
 {
   if(ms.empty())
     throw INTERP_KERNEL::Exception("MEDFileUMesh::setGroupsOnSetMesh : expecting a non empty vector !");
@@ -2637,7 +4516,7 @@ void MEDFileUMesh::setGroupsOnSetMesh(int meshDimRelToMax, const std::vector<con
   setGroupsAtLevel(meshDimRelToMax,corr2,renum);
 }
 
-DataArrayDouble *MEDFileUMesh::checkMultiMesh(const std::vector<const MEDCouplingUMesh *>& ms) const throw(INTERP_KERNEL::Exception)
+DataArrayDouble *MEDFileUMesh::checkMultiMesh(const std::vector<const MEDCouplingUMesh *>& ms) const
 {
   const DataArrayDouble *ret=ms[0]->getCoords();
   int mdim=ms[0]->getMeshDimension();
@@ -2652,7 +4531,15 @@ DataArrayDouble *MEDFileUMesh::checkMultiMesh(const std::vector<const MEDCouplin
   return const_cast<DataArrayDouble *>(ret);
 }
 
-void MEDFileUMesh::setFamilyFieldArr(int meshDimRelToMaxExt, DataArrayInt *famArr) throw(INTERP_KERNEL::Exception)
+/*!
+ * Sets the family field of a given relative dimension.
+ *  \param [in] meshDimRelToMaxExt - the relative dimension of entities for which
+ *          the family field is set.
+ *  \param [in] famArr - the array of the family field.
+ *  \throw If there are no mesh entities of \a meshDimRelToMaxExt dimension in \a this mesh.
+ *  \throw If \a famArr has an invalid size.
+ */
+void MEDFileUMesh::setFamilyFieldArr(int meshDimRelToMaxExt, DataArrayInt *famArr)
 {
   if(meshDimRelToMaxExt==1)
     {
@@ -2673,13 +4560,20 @@ void MEDFileUMesh::setFamilyFieldArr(int meshDimRelToMaxExt, DataArrayInt *famAr
     throw INTERP_KERNEL::Exception("MEDFileUMesh::setFamilyFieldArr : 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 !");
+    throw INTERP_KERNEL::Exception("Invalid mesh dim relative to max given ! Too low !");
   if((MEDFileUMeshSplitL1 *)_ms[traducedRk]==0)
     throw INTERP_KERNEL::Exception("On specified lev (or entity) no cells exists !");
   return _ms[traducedRk]->setFamilyArr(famArr);
 }
 
-void MEDFileUMesh::setRenumFieldArr(int meshDimRelToMaxExt, DataArrayInt *renumArr) throw(INTERP_KERNEL::Exception)
+/*!
+ * Sets the optional numbers of mesh entities of a given dimension.
+ *  \param [in] meshDimRelToMaxExt - the relative dimension of mesh entities.
+ *  \param [in] renumArr - the array of the numbers.
+ *  \throw If there are no mesh entities of \a meshDimRelToMaxExt dimension in \a this mesh.
+ *  \throw If \a renumArr has an invalid size.
+ */
+void MEDFileUMesh::setRenumFieldArr(int meshDimRelToMaxExt, DataArrayInt *renumArr)
 {
   if(meshDimRelToMaxExt==1)
     {
@@ -2702,12 +4596,46 @@ void MEDFileUMesh::setRenumFieldArr(int meshDimRelToMaxExt, DataArrayInt *renumA
     throw INTERP_KERNEL::Exception("MEDFileUMesh::setRenumArr : 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 !");
+    throw INTERP_KERNEL::Exception("Invalid mesh dim relative to max given ! Too low !");
   if((MEDFileUMeshSplitL1 *)_ms[traducedRk]==0)
     throw INTERP_KERNEL::Exception("On specified lev (or entity) no cells exists !");
   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)
+{
+  if(meshDimRelToMaxExt==1)
+    {
+      if(!nameArr)
+        {
+          _name_coords=0;
+          return ;
+        }
+      DataArrayDouble *coo(_coords);
+      if(!coo)
+        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::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 ! Too low !");
+  if((MEDFileUMeshSplitL1 *)_ms[traducedRk]==0)
+    throw INTERP_KERNEL::Exception("On specified lev (or entity) no cells exists !");
+  return _ms[traducedRk]->setNameArr(nameArr);
+}
+
 void MEDFileUMesh::synchronizeTinyInfoOnLeaves() const
 {
   for(std::vector< MEDCouplingAutoRefCountObjectPtr<MEDFileUMeshSplitL1> >::const_iterator it=_ms.begin();it!=_ms.end();it++)
@@ -2718,7 +4646,7 @@ void MEDFileUMesh::synchronizeTinyInfoOnLeaves() const
 /*!
  * This method is called by MEDFileMesh::changeFamilyId. It performs only one part of the family id modification.
  */
-void MEDFileUMesh::changeFamilyIdArr(int oldId, int newId) throw(INTERP_KERNEL::Exception)
+void MEDFileUMesh::changeFamilyIdArr(int oldId, int newId)
 {
   DataArrayInt *arr=_fam_coords;
   if(arr)
@@ -2762,25 +4690,51 @@ void MEDFileUMesh::computeRevNum() const
     }
 }
 
-std::size_t MEDFileStructuredMesh::getHeapMemorySize() const
+std::size_t MEDFileStructuredMesh::getHeapMemorySizeWithoutChildren() const
 {
-  std::size_t ret=MEDFileMesh::getHeapMemorySize();
-  if((const DataArrayInt*)_fam_nodes)
-    ret+=_fam_nodes->getHeapMemorySize();
-  if((const DataArrayInt*)_num_nodes)
-    ret+=_num_nodes->getHeapMemorySize();
-  if((const DataArrayInt*)_fam_cells)
-    ret+=_fam_cells->getHeapMemorySize();
-  if((const DataArrayInt*)_num_cells)
-    ret+=_num_cells->getHeapMemorySize();
-  if((const DataArrayInt*)_rev_num_nodes)
-    ret+=_rev_num_nodes->getHeapMemorySize();
-  if((const DataArrayInt*)_rev_num_cells)
-    ret+=_rev_num_cells->getHeapMemorySize();
+  return MEDFileMesh::getHeapMemorySizeWithoutChildren();
+}
+
+std::vector<const BigMemoryObject *> MEDFileStructuredMesh::getDirectChildrenWithNull() const
+{
+  std::vector<const BigMemoryObject *> ret(MEDFileMesh::getDirectChildrenWithNull());
+  ret.push_back((const DataArrayInt *)_fam_nodes);
+  ret.push_back((const DataArrayInt *)_num_nodes);
+  ret.push_back((const DataArrayAsciiChar *)_names_nodes);
+  ret.push_back((const DataArrayInt *)_fam_cells);
+  ret.push_back((const DataArrayInt *)_num_cells);
+  ret.push_back((const DataArrayAsciiChar *)_names_cells);
+  ret.push_back((const DataArrayInt *)_fam_faces);
+  ret.push_back((const DataArrayInt *)_num_faces);
+  ret.push_back((const DataArrayInt *)_rev_num_nodes);
+  ret.push_back((const DataArrayAsciiChar *)_names_faces);
+  ret.push_back((const DataArrayInt *)_rev_num_cells);
+  ret.push_back((const MEDCoupling1SGTUMesh*)_faces_if_necessary);
+  return ret;
+}
+
+int MEDFileStructuredMesh::getMaxAbsFamilyIdInArrays() const
+{
+  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));
+    }
+  if((const DataArrayInt *)_fam_faces)
+    {
+      int val=_fam_faces->getMaxValue(tmp);
+      ret=std::max(ret,std::abs(val));
+    }
   return ret;
 }
 
-int MEDFileStructuredMesh::getMaxFamilyIdInArrays() const throw(INTERP_KERNEL::Exception)
+int MEDFileStructuredMesh::getMaxFamilyIdInArrays() const
 {
   int ret=-std::numeric_limits<int>::max(),tmp=-1;
   if((const DataArrayInt *)_fam_nodes)
@@ -2793,10 +4747,15 @@ int MEDFileStructuredMesh::getMaxFamilyIdInArrays() const throw(INTERP_KERNEL::E
       int val=_fam_cells->getMaxValue(tmp);
       ret=std::max(ret,val);
     }
+  if((const DataArrayInt *)_fam_faces)
+    {
+      int val=_fam_faces->getMaxValue(tmp);
+      ret=std::max(ret,val);
+    }
   return ret;
 }
 
-int MEDFileStructuredMesh::getMinFamilyIdInArrays() const throw(INTERP_KERNEL::Exception)
+int MEDFileStructuredMesh::getMinFamilyIdInArrays() const
 {
   int ret=std::numeric_limits<int>::max(),tmp=-1;
   if((const DataArrayInt *)_fam_nodes)
@@ -2809,6 +4768,11 @@ int MEDFileStructuredMesh::getMinFamilyIdInArrays() const throw(INTERP_KERNEL::E
       int val=_fam_cells->getMinValue(tmp);
       ret=std::min(ret,val);
     }
+  if((const DataArrayInt *)_fam_faces)
+    {
+      int val=_fam_faces->getMinValue(tmp);
+      ret=std::min(ret,val);
+    }
   return ret;
 }
 
@@ -2854,6 +4818,22 @@ bool MEDFileStructuredMesh::isEqual(const MEDFileMesh *other, double eps, std::s
           return false;
         }
     }
+  famc1=_fam_faces;
+  famc2=otherC->_fam_faces;
+  if((famc1==0 && famc2!=0) || (famc1!=0 && famc2==0))
+    {
+      what="Mismatch of families arr on faces ! One is defined and not other !";
+      return false;
+    }
+  if(famc1)
+    {
+      bool ret=famc1->isEqual(*famc2);
+      if(!ret)
+        {
+          what="Families arr on faces differ !";
+          return false;
+        }
+    }
   famc1=_num_nodes;
   famc2=otherC->_num_nodes;
   if((famc1==0 && famc2!=0) || (famc1!=0 && famc2==0))
@@ -2886,6 +4866,70 @@ bool MEDFileStructuredMesh::isEqual(const MEDFileMesh *other, double eps, std::s
           return false;
         }
     }
+  famc1=_num_faces;
+  famc2=otherC->_num_faces;
+  if((famc1==0 && famc2!=0) || (famc1!=0 && famc2==0))
+    {
+      what="Mismatch of numbering arr on faces ! One is defined and not other !";
+      return false;
+    }
+  if(famc1)
+    {
+      bool ret=famc1->isEqual(*famc2);
+      if(!ret)
+        {
+          what="Numbering arr on faces differ !";
+          return false;
+        }
+    }
+  const DataArrayAsciiChar *d1=_names_cells;
+  const DataArrayAsciiChar *d2=otherC->_names_cells;
+  if((d1==0 && d2!=0) || (d1!=0 && d2==0))
+    {
+      what="Mismatch of naming arr on cells ! One is defined and not other !";
+      return false;
+    }
+  if(d1)
+    {
+      bool ret=d1->isEqual(*d2);
+      if(!ret)
+        {
+          what="Naming arr on cells differ !";
+          return false;
+        }
+    }
+  d1=_names_faces;
+  d2=otherC->_names_faces;
+  if((d1==0 && d2!=0) || (d1!=0 && d2==0))
+    {
+      what="Mismatch of naming arr on faces ! One is defined and not other !";
+      return false;
+    }
+  if(d1)
+    {
+      bool ret=d1->isEqual(*d2);
+      if(!ret)
+        {
+          what="Naming arr on faces differ !";
+          return false;
+        }
+    }
+  d1=_names_nodes;
+  d2=otherC->_names_nodes;
+  if((d1==0 && d2!=0) || (d1!=0 && d2==0))
+    {
+      what="Mismatch of naming arr on nodes ! One is defined and not other !";
+      return false;
+    }
+  if(d1)
+    {
+      bool ret=d1->isEqual(*d2);
+      if(!ret)
+        {
+          what="Naming arr on nodes differ !";
+          return false;
+        }
+    }
   return true;
 }
 
@@ -2904,116 +4948,336 @@ void MEDFileStructuredMesh::clearNonDiscrAttributes() const
   tmp=_num_cells;
   if(tmp)
     (const_cast<DataArrayInt *>(tmp))->setName("");
+  tmp=_fam_faces;
+  if(tmp)
+    (const_cast<DataArrayInt *>(tmp))->setName("");
+  tmp=_num_faces;
+  if(tmp)
+    (const_cast<DataArrayInt *>(tmp))->setName("");
 }
 
-DataArrayInt *MEDFileStructuredMesh::getFamiliesArr(int meshDimRelToMaxExt, const std::vector<std::string>& fams, bool renum) const throw(INTERP_KERNEL::Exception)
+/*!
+ * Returns ids of mesh entities contained in given families of a given dimension.
+ *  \param [in] meshDimRelToMaxExt - a relative dimension of the mesh entities whose ids
+ *          are required.
+ *  \param [in] fams - the names of the families of interest.
+ *  \param [in] renum - if \c true, the optional numbers of entities, if available, are
+ *          returned instead of ids.
+ *  \return DataArrayInt * - a new instance of DataArrayInt holding either ids or
+ *          numbers, if available and required, of mesh entities of the families. The caller
+ *          is to delete this array using decrRef() as it is no more needed. 
+ *  \throw If the family field is missing for \a meshDimRelToMaxExt.
+ */
+DataArrayInt *MEDFileStructuredMesh::getFamiliesArr(int meshDimRelToMaxExt, const std::vector<std::string>& fams, bool renum) const
 {
-  if(meshDimRelToMaxExt!=0 && meshDimRelToMaxExt!=1)
-    throw INTERP_KERNEL::Exception("MEDFileStructuredMesh::getFamiliesArr : Only available for levels 0 or 1 !");
-  std::vector<int> famIds=getFamiliesIds(fams);
-  if(meshDimRelToMaxExt==1)
-    {
-      if((const DataArrayInt *)_fam_nodes)
-        {
-          MEDCouplingAutoRefCountObjectPtr<DataArrayInt> da;
-          if(!famIds.empty())
-            da=_fam_nodes->getIdsEqualList(&famIds[0],&famIds[0]+famIds.size());
-          else
-            da=_fam_nodes->getIdsEqualList(0,0);
-          if(renum)
-            return MEDFileUMeshSplitL1::Renumber(_num_nodes,da);
-          else
-            return da.retn();
-        }
-      else
-        throw INTERP_KERNEL::Exception("MEDFileStructuredMesh::getFamiliesArr : no family array specified on nodes !");
-    }
-  else
-    {
-      if((const DataArrayInt *)_fam_cells)
-        {
-          MEDCouplingAutoRefCountObjectPtr<DataArrayInt> da;
-          if(!famIds.empty())
-            da=_fam_cells->getIdsEqualList(&famIds[0],&famIds[0]+famIds.size());
-          else
-            da=_fam_cells->getIdsEqualList(0,0);
-          if(renum)
-            return MEDFileUMeshSplitL1::Renumber(_num_cells,da);
-          else
-            return da.retn();
-        }
-      else
-        throw INTERP_KERNEL::Exception("MEDFileStructuredMesh::getFamiliesArr : no family array specified on cells !");
-    }
+  std::vector<int> famIds(getFamiliesIds(fams));
+  switch(meshDimRelToMaxExt)
+  {
+    case 1:
+      {
+        if((const DataArrayInt *)_fam_nodes)
+          {
+            MEDCouplingAutoRefCountObjectPtr<DataArrayInt> da;
+            if(!famIds.empty())
+              da=_fam_nodes->getIdsEqualList(&famIds[0],&famIds[0]+famIds.size());
+            else
+              da=_fam_nodes->getIdsEqualList(0,0);
+            if(renum)
+              return MEDFileUMeshSplitL1::Renumber(_num_nodes,da);
+            else
+              return da.retn();
+          }
+        else
+          throw INTERP_KERNEL::Exception("MEDFileStructuredMesh::getFamiliesArr : no family array specified on nodes !");
+        break;
+      }
+    case 0:
+      {
+        if((const DataArrayInt *)_fam_cells)
+          {
+            MEDCouplingAutoRefCountObjectPtr<DataArrayInt> da;
+            if(!famIds.empty())
+              da=_fam_cells->getIdsEqualList(&famIds[0],&famIds[0]+famIds.size());
+            else
+              da=_fam_cells->getIdsEqualList(0,0);
+            if(renum)
+              return MEDFileUMeshSplitL1::Renumber(_num_cells,da);
+            else
+              return da.retn();
+          }
+        else
+          throw INTERP_KERNEL::Exception("MEDFileStructuredMesh::getFamiliesArr : no family array specified on cells !");
+        break;
+      }
+    case -1:
+      {
+        if((const DataArrayInt *)_fam_faces)
+          {
+            MEDCouplingAutoRefCountObjectPtr<DataArrayInt> da;
+            if(!famIds.empty())
+              da=_fam_faces->getIdsEqualList(&famIds[0],&famIds[0]+famIds.size());
+            else
+              da=_fam_faces->getIdsEqualList(0,0);
+            if(renum)
+              return MEDFileUMeshSplitL1::Renumber(_num_faces,da);
+            else
+              return da.retn();
+          }
+        else
+          throw INTERP_KERNEL::Exception("MEDFileStructuredMesh::getFamiliesArr : no family array specified on faces !");
+        break;
+      }
+    default:
+      throw INTERP_KERNEL::Exception("MEDFileStructuredMesh::getFamiliesArr : input meshDimRelative must be in [0,1,-1] !");
+  }
+  throw INTERP_KERNEL::Exception("MEDFileStructuredMesh::getFamiliesArr : unmanaged case !");
 }
 
-void MEDFileStructuredMesh::setFamilyFieldArr(int meshDimRelToMaxExt, DataArrayInt *famArr) throw(INTERP_KERNEL::Exception)
+/*!
+ * Sets the family field of a given relative dimension.
+ *  \param [in] meshDimRelToMaxExt - the relative dimension of entities for which
+ *          the family field is set.
+ *  \param [in] famArr - the array of the family field.
+ *  \throw If there are no mesh entities of \a meshDimRelToMaxExt dimension in \a this mesh.
+ *  \throw If \a famArr has an invalid size.
+ *  \throw If \a meshDimRelToMaxExt != 0 and \a meshDimRelToMaxExt != 1 and \a meshDimRelToMaxExt != -1.
+ */
+void MEDFileStructuredMesh::setFamilyFieldArr(int meshDimRelToMaxExt, DataArrayInt *famArr)
 {
-  if(meshDimRelToMaxExt!=0 && meshDimRelToMaxExt!=1)
-    throw INTERP_KERNEL::Exception("MEDFileStructuredMesh::setRenumFieldArr : Only available for levels 0 or 1 !");
-  const MEDCouplingStructuredMesh *mesh=getStructuredMesh();
+  const MEDCouplingStructuredMesh *mesh(getStructuredMesh());
   if(!mesh)
     throw INTERP_KERNEL::Exception("MEDFileStructuredMesh::setFamilyFieldArr : no structured mesh specified ! Impossible to set family array !");
-  if(meshDimRelToMaxExt==0)
-    {
-      int nbCells=mesh->getNumberOfCells();
-      famArr->checkNbOfTuplesAndComp(nbCells,1,"MEDFileStructuredMesh::setFamilyArr : Problem in size of Family arr ! Mismatch with number of cells of mesh !");
-      _fam_cells=famArr;
-    }
-  else
-    {
-      int nbNodes=mesh->getNumberOfNodes();
-      famArr->checkNbOfTuplesAndComp(nbNodes,1,"MEDFileStructuredMesh::setFamilyArr : Problem in size of Family arr ! Mismatch with number of nodes of mesh !");
-      _fam_nodes=famArr;
-    }
+  switch(meshDimRelToMaxExt)
+  {
+    case 0:
+      {
+        int nbCells=mesh->getNumberOfCells();
+        famArr->checkNbOfTuplesAndComp(nbCells,1,"MEDFileStructuredMesh::setFamilyFieldArr : Problem in size of Family arr ! Mismatch with number of cells of mesh !");
+        _fam_cells=famArr;
+        break;
+      }
+    case 1:
+      {
+        int nbNodes=mesh->getNumberOfNodes();
+        famArr->checkNbOfTuplesAndComp(nbNodes,1,"MEDFileStructuredMesh::setFamilyFieldArr : Problem in size of Family arr ! Mismatch with number of nodes of mesh !");
+        _fam_nodes=famArr;
+        break;
+      }
+    case -1:
+      {
+        int nbCells=mesh->getNumberOfCellsOfSubLevelMesh();
+        famArr->checkNbOfTuplesAndComp(nbCells,1,"MEDFileStructuredMesh::setFamilyFieldArr : Problem in size of Family arr ! Mismatch with number of faces of mesh !");
+        _fam_faces=famArr;
+        break;
+      }
+    default:
+      throw INTERP_KERNEL::Exception("MEDFileStructuredMesh::setFamilyFieldArr : Only available for levels 0 or 1 or -1 !");
+  }
   if(famArr)
     famArr->incrRef();
 }
 
-void MEDFileStructuredMesh::setRenumFieldArr(int meshDimRelToMaxExt, DataArrayInt *renumArr) throw(INTERP_KERNEL::Exception)
+/*!
+ * Sets the optional numbers of mesh entities of a given dimension.
+ *  \param [in] meshDimRelToMaxExt - the relative dimension of mesh entities.
+ *  \param [in] renumArr - the array of the numbers.
+ *  \throw If there are no mesh entities of \a meshDimRelToMaxExt dimension in \a this mesh.
+ *  \throw If \a renumArr has an invalid size.
+ *  \throw If \a meshDimRelToMaxExt != 0 and \a meshDimRelToMaxExt != 1.
+ */
+void MEDFileStructuredMesh::setRenumFieldArr(int meshDimRelToMaxExt, DataArrayInt *renumArr)
 {
-  if(meshDimRelToMaxExt!=0 && meshDimRelToMaxExt!=1)
-    throw INTERP_KERNEL::Exception("MEDFileStructuredMesh::setRenumFieldArr : Only available for levels 0 or 1 !");
   const MEDCouplingStructuredMesh *mesh=getStructuredMesh();
   if(!mesh)
     throw INTERP_KERNEL::Exception("MEDFileStructuredMesh::setRenumFieldArr : no structured mesh specified ! Impossible to set number array !");
-  if(meshDimRelToMaxExt==0)
-    {
-      int nbCells=mesh->getNumberOfCells();
-      renumArr->checkNbOfTuplesAndComp(nbCells,1,"MEDFileStructuredMesh::setRenumFieldArr : Problem in size of Renum arr ! Mismatch with number of cells of mesh !");
-      _num_cells=renumArr;
-    }
-  else
-    {
-      int nbNodes=mesh->getNumberOfNodes();
-      renumArr->checkNbOfTuplesAndComp(nbNodes,1,"MEDFileStructuredMesh::setFamilyArr : Problem in size of Family arr ! Mismatch with number of nodes of mesh !");
-      _num_nodes=renumArr;
-    }
+  switch(meshDimRelToMaxExt)
+  {
+    case 0:
+      {
+        int nbCells=mesh->getNumberOfCells();
+        renumArr->checkNbOfTuplesAndComp(nbCells,1,"MEDFileStructuredMesh::setRenumFieldArr : Problem in size of Renum arr ! Mismatch with number of cells of mesh !");
+        _num_cells=renumArr;
+        break;
+      }
+    case 1:
+      {
+        int nbNodes=mesh->getNumberOfNodes();
+        renumArr->checkNbOfTuplesAndComp(nbNodes,1,"MEDFileStructuredMesh::setRenumFieldArr : Problem in size of Family arr ! Mismatch with number of nodes of mesh !");
+        _num_nodes=renumArr;
+        break;
+      }
+    case -1:
+      {
+        int nbCells=mesh->getNumberOfCellsOfSubLevelMesh();
+        renumArr->checkNbOfTuplesAndComp(nbCells,1,"MEDFileStructuredMesh::setRenumFieldArr : Problem in size of Renum arr ! Mismatch with number of faces of mesh !");
+        _num_faces=renumArr;
+        break;
+      }
+    default:
+      throw INTERP_KERNEL::Exception("MEDFileStructuredMesh::setRenumFieldArr : Only available for levels 0 or 1 or -1 !");
+  }
   if(renumArr)
     renumArr->incrRef();
 }
 
-const DataArrayInt *MEDFileStructuredMesh::getFamilyFieldAtLevel(int meshDimRelToMaxExt) const throw(INTERP_KERNEL::Exception)
+/*!
+ * 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)
 {
-  if(meshDimRelToMaxExt!=0 && meshDimRelToMaxExt!=1)
-    throw INTERP_KERNEL::Exception("MEDFileStructuredMesh::getFamilyFieldAtLevel : Only available for levels 0 or 1 !");
-  if(meshDimRelToMaxExt==0)
-    return _fam_cells;
-  else
-    return _fam_nodes;
+  const MEDCouplingStructuredMesh *mesh(getStructuredMesh());
+  if(!mesh)
+    throw INTERP_KERNEL::Exception("MEDFileStructuredMesh::setNameFieldAtLevel : no structured mesh specified ! Impossible to set names array !");
+  switch(meshDimRelToMaxExt)
+  {
+    case 0:
+      {
+        int nbCells=mesh->getNumberOfCells();
+        nameArr->checkNbOfTuplesAndComp(nbCells,MED_SNAME_SIZE,"MEDFileStructuredMesh::setNameFieldAtLevel : Problem in size of names arr ! Mismatch with number of cells of mesh !");
+        _names_cells=nameArr;
+        break;
+      }
+    case 1:
+      {
+        int nbNodes=mesh->getNumberOfNodes();
+        nameArr->checkNbOfTuplesAndComp(nbNodes,MED_SNAME_SIZE,"MEDFileStructuredMesh::setNameFieldAtLevel : Problem in size of names arr ! Mismatch with number of nodes of mesh !");
+        _names_nodes=nameArr;
+        break;
+      }
+    case -1:
+      {
+        int nbCells=mesh->getNumberOfCellsOfSubLevelMesh();
+        nameArr->checkNbOfTuplesAndComp(nbCells,MED_SNAME_SIZE,"MEDFileStructuredMesh::setNameFieldAtLevel : Problem in size of names arr ! Mismatch with number of faces of mesh !");
+        _names_cells=nameArr;
+      }
+    default:
+      throw INTERP_KERNEL::Exception("MEDFileStructuredMesh::setNameFieldAtLevel : Only available for levels 0 or 1 or -1 !");
+  }
+  if(nameArr)
+    nameArr->incrRef();
 }
 
-const DataArrayInt *MEDFileStructuredMesh::getNumberFieldAtLevel(int meshDimRelToMaxExt) const throw(INTERP_KERNEL::Exception)
+/*!
+ * Adds a group of nodes 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).
+ *
+ *  \warning this method can alter default "FAMILLE_ZERO" family.
+ *  For users sensitive to this a call to MEDFileMesh::rearrangeFamilies will be necessary after addGroup session.
+ *
+ *  \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 MEDFileStructuredMesh::addNodeGroup(const DataArrayInt *ids)
 {
-  if(meshDimRelToMaxExt!=0 && meshDimRelToMaxExt!=1)
-    throw INTERP_KERNEL::Exception("MEDFileStructuredMesh::getNumberFieldAtLevel : Only available for levels 0 or 1 !");
-  if(meshDimRelToMaxExt==0)
-    return _num_cells;
-  else
-    return _num_nodes;
+  addGroup(1,ids);
+}
+
+/*!
+ * 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).
+ *
+ * \warning this method can alter default "FAMILLE_ZERO" family.
+ * For users sensitive to this a call to MEDFileMesh::rearrangeFamilies will be necessary after addGroup session.
+ *
+ *  \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 MEDFileStructuredMesh::addGroup(int meshDimRelToMaxExt, const DataArrayInt *ids)
+{
+  DataArrayInt *fam(getOrCreateAndGetFamilyFieldAtLevel(meshDimRelToMaxExt));
+  addGroupUnderground(false,ids,fam);
+  return ;
 }
 
-const DataArrayInt *MEDFileStructuredMesh::getRevNumberFieldAtLevel(int meshDimRelToMaxExt) const throw(INTERP_KERNEL::Exception)
+/*!
+ * Returns the family field for mesh entities of a given dimension.
+ *  \param [in] meshDimRelToMaxExt - the relative dimension of mesh entities.
+ *  \return const DataArrayInt * - the family field. It is an array of ids of families
+ *          each mesh entity belongs to. It can be \c NULL.
+ *  \throw If \a meshDimRelToMaxExt != 0 and \a meshDimRelToMaxExt != 1.
+ */
+const DataArrayInt *MEDFileStructuredMesh::getFamilyFieldAtLevel(int meshDimRelToMaxExt) const
+{
+  switch(meshDimRelToMaxExt)
+  {
+    case 0:
+      return _fam_cells;
+    case 1:
+      return _fam_nodes;
+    case -1:
+      return _fam_faces;
+    default:
+      throw INTERP_KERNEL::Exception("MEDFileStructuredMesh::getFamilyFieldAtLevel : Only available for levels 0 or 1 or -1 !");
+  }
+}
+
+/*!
+ * Returns the family field for mesh entities of a given dimension.
+ *  \param [in] meshDimRelToMaxExt - the relative dimension of mesh entities.
+ *  \return const DataArrayInt * - the family field. It is an array of ids of families
+ *          each mesh entity belongs to. It can be \c NULL.
+ *  \throw If \a meshDimRelToMaxExt != 0 and \a meshDimRelToMaxExt != 1.
+ */
+DataArrayInt *MEDFileStructuredMesh::getFamilyFieldAtLevel(int meshDimRelToMaxExt)
+{
+  switch(meshDimRelToMaxExt)
+  {
+    case 0:
+      return _fam_cells;
+    case 1:
+      return _fam_nodes;
+    case -1:
+      return _fam_faces;
+    default:
+      throw INTERP_KERNEL::Exception("MEDFileStructuredMesh::getFamilyFieldAtLevel : Only available for levels 0 or 1 or -1 !");
+  }
+}
+
+/*!
+ * Returns the optional numbers of mesh entities of a given dimension.
+ *  \param [in] meshDimRelToMaxExt - the relative dimension of mesh entities.
+ *  \return const DataArrayInt * - the array of the entity numbers.
+ *  \throw If there are no mesh entities of \a meshDimRelToMaxExt dimension in \a this mesh.
+ *  \throw If \a meshDimRelToMaxExt != 0 and \a meshDimRelToMaxExt != 1.
+ */
+const DataArrayInt *MEDFileStructuredMesh::getNumberFieldAtLevel(int meshDimRelToMaxExt) const
+{
+  switch(meshDimRelToMaxExt)
+  {
+    case 0:
+      return _num_cells;
+    case 1:
+      return _num_nodes;
+    case -1:
+      return _num_faces;
+    default:
+      throw INTERP_KERNEL::Exception("MEDFileStructuredMesh::getNumberFieldAtLevel : Only available for levels 0 or 1 or -1 !");
+  }
+}
+
+/*!
+ * Returns the optional numbers of mesh entities of a given dimension transformed using
+ * DataArrayInt::invertArrayN2O2O2N().
+ *  \param [in] meshDimRelToMaxExt - the relative dimension of mesh entities.
+ *  \return const DataArrayInt * - the array of the entity numbers transformed using
+ *          DataArrayInt::invertArrayN2O2O2N().
+ *  \throw If \a meshDimRelToMaxExt != 0 and \a meshDimRelToMaxExt != 1.
+ *  \throw If there are no mesh entities of \a meshDimRelToMaxExt dimension in \a this mesh.
+ */
+const DataArrayInt *MEDFileStructuredMesh::getRevNumberFieldAtLevel(int meshDimRelToMaxExt) const
 {
   if(meshDimRelToMaxExt!=0 && meshDimRelToMaxExt!=1)
     throw INTERP_KERNEL::Exception("MEDFileStructuredMesh::getRevNumberFieldAtLevel : Only available for levels 0 or 1 !");
@@ -3043,12 +5307,35 @@ const DataArrayInt *MEDFileStructuredMesh::getRevNumberFieldAtLevel(int meshDimR
     }
 }
 
+const DataArrayAsciiChar *MEDFileStructuredMesh::getNameFieldAtLevel(int meshDimRelToMaxExt) const
+{
+  switch(meshDimRelToMaxExt)
+  {
+    case 0:
+      return _names_cells;
+    case 1:
+      return _names_nodes;
+    case -1:
+      return _names_faces;
+    default:
+      throw INTERP_KERNEL::Exception("MEDFileStructuredMesh::getNameFieldAtLevel : Only available for levels 0 or 1 or -1 !");
+  }
+}
+
+/*!
+ * Returns relative dimensions of mesh entities (excluding nodes) present in \a this mesh.
+ *  \return std::vector<int> - a sequence of the relative dimensions: [0].
+ */
 std::vector<int> MEDFileStructuredMesh::getNonEmptyLevels() const
 {
   std::vector<int> ret(1);
   return ret;
 }
 
+/*!
+ * Returns relative dimensions of mesh entities (including nodes) present in \a this mesh.
+ *  \return std::vector<int> - a sequence of the relative dimensions: [1,0].
+ */
 std::vector<int> MEDFileStructuredMesh::getNonEmptyLevelsExt() const
 {
   std::vector<int> ret(2);
@@ -3056,16 +5343,64 @@ 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),*famFaces(_fam_faces);
+  if(famNodes)
+    ret.push_back(1);
+  if(famCells)
+    ret.push_back(0);
+  if(famFaces)
+    ret.push_back(-1);
+  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),*numFaces(_num_faces);
+  if(numNodes)
+    ret.push_back(1);
+  if(numCells)
+    ret.push_back(0);
+  if(numFaces)
+    ret.push_back(-1);
+  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 *namesNodes(_names_nodes),*namesCells(_names_cells),*namesFaces(_names_faces);
+  if(namesNodes)
+    ret.push_back(1);
+  if(namesCells)
+    ret.push_back(0);
+  if(namesFaces)
+    ret.push_back(-1);
+  return ret;
+}
+
 /*!
  * no implementation here, it is not a bug, but intresically no polyhedra in \a this.
  */
-bool MEDFileStructuredMesh::unPolyze(std::vector<int>& oldCode, std::vector<int>& newCode, DataArrayInt *& o2nRenumCell) throw(INTERP_KERNEL::Exception)
+bool MEDFileStructuredMesh::unPolyze(std::vector<int>& oldCode, std::vector<int>& newCode, DataArrayInt *& o2nRenumCell)
 {
   oldCode.clear(); newCode.clear(); o2nRenumCell=0;
   return false;
 }
 
-void MEDFileStructuredMesh::changeFamilyIdArr(int oldId, int newId) throw(INTERP_KERNEL::Exception)
+void MEDFileStructuredMesh::changeFamilyIdArr(int oldId, int newId)
 {
   DataArrayInt *arr=_fam_nodes;
   if(arr)
@@ -3073,18 +5408,46 @@ void MEDFileStructuredMesh::changeFamilyIdArr(int oldId, int newId) throw(INTERP
   arr=_fam_cells;
   if(arr)
     arr->changeValue(oldId,newId);
+  arr=_fam_faces;
+  if(arr)
+    arr->changeValue(oldId,newId);
 }
 
-void MEDFileStructuredMesh::deepCpyAttributes() throw(INTERP_KERNEL::Exception)
+std::list< MEDCouplingAutoRefCountObjectPtr<DataArrayInt> > MEDFileStructuredMesh::getAllNonNullFamilyIds() const
+{
+  std::list< MEDCouplingAutoRefCountObjectPtr<DataArrayInt> > ret;
+  const DataArrayInt *da(_fam_nodes);
+  if(da)
+    { da->incrRef(); ret.push_back(MEDCouplingAutoRefCountObjectPtr<DataArrayInt>(const_cast<DataArrayInt *>(da))); }
+  da=_fam_cells;
+  if(da)
+    { da->incrRef(); ret.push_back(MEDCouplingAutoRefCountObjectPtr<DataArrayInt>(const_cast<DataArrayInt *>(da))); }
+  da=_fam_faces;
+  if(da)
+    { da->incrRef(); ret.push_back(MEDCouplingAutoRefCountObjectPtr<DataArrayInt>(const_cast<DataArrayInt *>(da))); }
+  return ret;
+}
+
+void MEDFileStructuredMesh::deepCpyAttributes()
 {
   if((const DataArrayInt*)_fam_nodes)
     _fam_nodes=_fam_nodes->deepCpy();
   if((const DataArrayInt*)_num_nodes)
     _num_nodes=_num_nodes->deepCpy();
+  if((const DataArrayAsciiChar*)_names_nodes)
+    _names_nodes=_names_nodes->deepCpy();
   if((const DataArrayInt*)_fam_cells)
     _fam_cells=_fam_cells->deepCpy();
   if((const DataArrayInt*)_num_cells)
     _num_cells=_num_cells->deepCpy();
+  if((const DataArrayAsciiChar*)_names_cells)
+    _names_cells=_names_cells->deepCpy();
+  if((const DataArrayInt*)_fam_faces)
+    _fam_faces=_fam_faces->deepCpy();
+  if((const DataArrayInt*)_num_faces)
+    _num_faces=_num_faces->deepCpy();
+  if((const DataArrayAsciiChar*)_names_faces)
+    _names_faces=_names_faces->deepCpy();
   if((const DataArrayInt*)_rev_num_nodes)
     _rev_num_nodes=_rev_num_nodes->deepCpy();
   if((const DataArrayInt*)_rev_num_cells)
@@ -3097,127 +5460,372 @@ void MEDFileStructuredMesh::deepCpyAttributes() throw(INTERP_KERNEL::Exception)
  * \return a pointer to cartesian mesh that need to be managed by the caller.
  * \warning the returned pointer has to be managed by the caller.
  */
-MEDCouplingMesh *MEDFileStructuredMesh::getGenMeshAtLevel(int meshDimRelToMax, bool renum) const throw(INTERP_KERNEL::Exception)
+
+/*!
+ * Returns a pointer to MEDCouplingStructuredMesh held by \a this. 
+ *  \param [in] meshDimRelToMax - it must be \c 0 or \c -1.
+ *  \param [in] renum - it must be \c false.
+ *  \return MEDCouplingMesh * - a pointer to MEDCouplingMesh that the caller is to
+ *          delete using decrRef() as it is no more needed. 
+ */
+MEDCouplingMesh *MEDFileStructuredMesh::getGenMeshAtLevel(int meshDimRelToMax, bool renum) const
 {
   if(renum)
     throw INTERP_KERNEL::Exception("MEDFileCurveLinearMesh does not support renumbering ! To do it perform request of renum array directly !");
-  if(meshDimRelToMax!=0)
-    throw INTERP_KERNEL::Exception("MEDFileCurveLinearMesh does not support multi level for mesh 0 expected as input !");
-  const MEDCouplingStructuredMesh *m=getStructuredMesh();
-  if(m)
-    m->incrRef();
-  return const_cast<MEDCouplingStructuredMesh *>(m);
+  const MEDCouplingStructuredMesh *m(getStructuredMesh());
+  switch(meshDimRelToMax)
+  {
+    case 0:
+      {
+        if(m)
+          m->incrRef();
+        return const_cast<MEDCouplingStructuredMesh *>(m);
+      }
+    case -1:
+      {
+        if(!m)
+          throw INTERP_KERNEL::Exception("MEDFileStructuredMesh::getGenMeshAtLevel : level -1 requested must be non empty to be able to compute unstructured sub mesh !");
+        buildMinusOneImplicitPartIfNeeded();
+        MEDCouplingMesh *ret(_faces_if_necessary);
+        if(ret)
+          ret->incrRef();
+        return ret;
+      }
+    default:
+      throw INTERP_KERNEL::Exception("MEDFileCurveLinearMesh does not support multi level for mesh 0 expected as input !");
+  }
 }
 
-int MEDFileStructuredMesh::getSizeAtLevel(int meshDimRelToMaxExt) const throw(INTERP_KERNEL::Exception)
+/*!
+ * Returns number of mesh entities of a given relative dimension in \a this mesh.
+ *  \param [in] meshDimRelToMaxExt - the relative dimension of interest.
+ *  \return int - the number of entities.
+ *  \throw If no mesh entities of dimension \a meshDimRelToMaxExt are available in \a this mesh.
+ */
+int MEDFileStructuredMesh::getSizeAtLevel(int meshDimRelToMaxExt) const
 {
-  if(meshDimRelToMaxExt!=0 && meshDimRelToMaxExt!=1)
-    throw INTERP_KERNEL::Exception("MEDFileStructuredMesh::getSizeAtLevel : Only available for levels 0 or 1 !");
-  const MEDCouplingStructuredMesh *cmesh=getStructuredMesh();
+  const MEDCouplingStructuredMesh *cmesh(getStructuredMesh());
   if(!cmesh)
     throw INTERP_KERNEL::Exception("MEDFileStructuredMesh::getSizeAtLevel : No structured mesh set !");
-  if(meshDimRelToMaxExt==0)
-    return cmesh->getNumberOfCells();
-  else
-    return cmesh->getNumberOfNodes();
+  switch(meshDimRelToMaxExt)
+  {
+    case 0:
+      return cmesh->getNumberOfCells();
+    case 1:
+      return cmesh->getNumberOfNodes();
+    case -1:
+      return cmesh->getNumberOfCellsOfSubLevelMesh();
+    default:
+      throw INTERP_KERNEL::Exception("MEDFileStructuredMesh::getSizeAtLevel : Only available for levels 0 or 1 or -1 !");
+  }
 }
 
-int MEDFileStructuredMesh::getNumberOfNodes() const throw(INTERP_KERNEL::Exception)
+int MEDFileStructuredMesh::getNumberOfNodes() const
 {
-  const MEDCouplingStructuredMesh *cmesh=getStructuredMesh();
+  const MEDCouplingStructuredMesh *cmesh(getStructuredMesh());
   if(!cmesh)
     throw INTERP_KERNEL::Exception("MEDFileStructuredMesh::getNumberOfNodes : no cartesian mesh set !");
   return cmesh->getNumberOfNodes();
 }
 
-med_geometry_type MEDFileStructuredMesh::GetGeoTypeFromMeshDim(int meshDim) throw(INTERP_KERNEL::Exception)
+int MEDFileStructuredMesh::getNumberOfCellsAtLevel(int meshDimRelToMaxExt) const
+{
+  const MEDCouplingStructuredMesh *cmesh(getStructuredMesh());
+  if(!cmesh)
+    throw INTERP_KERNEL::Exception("MEDFileStructuredMesh::getNumberOfNodes : no cartesian mesh set !");
+  switch(meshDimRelToMaxExt)
+  {
+    case 0:
+      return cmesh->getNumberOfCells();
+    case -1:
+      return cmesh->getNumberOfCellsOfSubLevelMesh();
+    default:
+      throw INTERP_KERNEL::Exception("MEDFileStructuredMesh::getNumberOfNodes : only meshDimRelToMax=0 and meshDimRelToMax=-1 supported !");
+    }
+}
+
+bool MEDFileStructuredMesh::hasImplicitPart() const
+{
+  return true;
+}
+
+/*!
+ * \sa MEDFileStructuredMesh::getImplicitFaceMesh
+ */
+int MEDFileStructuredMesh::buildImplicitPartIfAny(INTERP_KERNEL::NormalizedCellType gt) const
 {
-  med_geometry_type geoTypeReq=MED_NONE;
-  switch(meshDim)
+  static const char MSG[]="MEDFileStructuredMesh::buildImplicitPartIfAny : the given geo type is not manageable by a structured mesh !";
+  const MEDCoupling1SGTUMesh *zeFaceMesh(_faces_if_necessary);
+  if(!zeFaceMesh)
     {
-    case 3:
-      geoTypeReq=MED_HEXA8;
-      break;
-    case 2:
-      geoTypeReq=MED_QUAD4;
-      break;
-    case 1:
-      geoTypeReq=MED_SEG2;
-      break;
+      const INTERP_KERNEL::CellModel& cm(INTERP_KERNEL::CellModel::GetCellModel(MEDCouplingStructuredMesh::GetGeoTypeGivenMeshDimension(getMeshDimension())));
+      if(cm.getReverseExtrudedType()!=gt)
+        throw INTERP_KERNEL::Exception(MSG);
+      buildImplicitPart();
+      return getStructuredMesh()->getNumberOfCellsOfSubLevelMesh();
+    }
+  else
+    {
+      if(gt!=zeFaceMesh->getCellModelEnum())
+        throw INTERP_KERNEL::Exception(MSG);
+      return zeFaceMesh->getNumberOfCells();
+    }
+}
+
+void MEDFileStructuredMesh::buildMinusOneImplicitPartIfNeeded() const
+{
+  const MEDCoupling1SGTUMesh *zeFaceMesh(_faces_if_necessary);
+  if(!zeFaceMesh)
+    buildImplicitPart();
+}
+
+void MEDFileStructuredMesh::buildImplicitPart() const
+{
+  const MEDCouplingStructuredMesh *mcmesh(getStructuredMesh());
+  if(!mcmesh)
+    throw INTERP_KERNEL::Exception("MEDFileStructuredMesh::buildImplicitPart : Unable to build the implicit part of structured mesh because no structured mesh at level 0 defined !");
+  _faces_if_necessary=mcmesh->build1SGTSubLevelMesh();
+}
+
+void MEDFileStructuredMesh::releaseImplicitPartIfAny() const
+{
+  _faces_if_necessary=0;
+}
+
+/*!
+ * Retrieves the internal pointer (no decrRef requested) of the implicit face mesh if any.
+ * To force to build it you can invoke MEDFileStructuredMesh::buildImplicitPartIfAny method.
+ * 
+ * \sa MEDFileStructuredMesh::buildImplicitPartIfAny
+ */
+MEDCoupling1SGTUMesh *MEDFileStructuredMesh::getImplicitFaceMesh() const
+{
+  return _faces_if_necessary;
+}
+
+std::vector<INTERP_KERNEL::NormalizedCellType> MEDFileStructuredMesh::getGeoTypesAtLevel(int meshDimRelToMax) const
+{
+  const MEDCouplingStructuredMesh *cmesh(getStructuredMesh());
+  if(!cmesh)
+    throw INTERP_KERNEL::Exception("MEDFileStructuredMesh::getGeoTypesAtLevel : No structured mesh set !");
+  switch(meshDimRelToMax)
+  {
     case 0:
-      geoTypeReq=MED_POINT1;
-      break;
+      {
+        std::vector<INTERP_KERNEL::NormalizedCellType> ret(1,cmesh->getTypeOfCell(0));
+        return ret;
+      }
+    case -1:
+      {
+        int mdim(cmesh->getMeshDimension());
+        if(mdim<1)
+          throw INTERP_KERNEL::Exception("MEDFileStructuredMesh::getGeoTypesAtLevel : only one level available for structured meshes ! Input 0 is mandatory or 0D mesh !");
+        std::vector<INTERP_KERNEL::NormalizedCellType> ret(1,MEDCouplingStructuredMesh::GetGeoTypeGivenMeshDimension(mdim-1));
+        return ret;
+      }
     default:
-      throw INTERP_KERNEL::Exception("Invalid meshdim detected for structured mesh ! Must be in (1,2,3) !");
+      throw INTERP_KERNEL::Exception("MEDFileStructuredMesh::getGeoTypesAtLevel : only 2 levels available at most : 0 and -1 !");
+  }
+}
+
+void MEDFileStructuredMesh::whichAreNodesFetched(const MEDFileField1TSStructItem& st, const MEDFileFieldGlobsReal *globs, std::vector<bool>& nodesFetched) const
+{
+  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()));
+  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)
+{
+  INTERP_KERNEL::NormalizedCellType ct(MEDCouplingStructuredMesh::GetGeoTypeGivenMeshDimension(meshDim));
+  return typmai3[ct];
+}
+
+void MEDFileStructuredMesh::LoadStrMeshDAFromFile(med_idt fid, int meshDim, int dt, int it, const std::string& mName, MEDFileMeshReadSelector *mrs,
+                                                  MEDCouplingAutoRefCountObjectPtr<DataArrayInt>& famCells, MEDCouplingAutoRefCountObjectPtr<DataArrayInt>& numCells, MEDCouplingAutoRefCountObjectPtr<DataArrayAsciiChar>& namesCells)
+{
+  med_bool chgt=MED_FALSE,trsf=MED_FALSE;
+  med_geometry_type geoTypeReq=MEDFileStructuredMesh::GetGeoTypeFromMeshDim(meshDim);
+  int nbOfElt(0);
+  nbOfElt=MEDmeshnEntity(fid,mName.c_str(),dt,it,MED_CELL,geoTypeReq,MED_FAMILY_NUMBER,MED_NODAL,&chgt,&trsf);
+  if(nbOfElt>0)
+    {
+      if(!mrs || mrs->isCellFamilyFieldReading())
+        {
+          famCells=DataArrayInt::New();
+          famCells->alloc(nbOfElt,1);
+          MEDFILESAFECALLERRD0(MEDmeshEntityFamilyNumberRd,(fid,mName.c_str(),dt,it,MED_CELL,geoTypeReq,famCells->getPointer()));
+        }
+    }
+  nbOfElt=MEDmeshnEntity(fid,mName.c_str(),dt,it,MED_CELL,geoTypeReq,MED_NUMBER,MED_NODAL,&chgt,&trsf);
+  if(nbOfElt>0)
+    {
+      if(!mrs || mrs->isCellNumFieldReading())
+        {
+          numCells=DataArrayInt::New();
+          numCells->alloc(nbOfElt,1);
+          MEDFILESAFECALLERRD0(MEDmeshEntityNumberRd,(fid,mName.c_str(),dt,it,MED_CELL,geoTypeReq,numCells->getPointer()));
+        }
+    }
+  nbOfElt=MEDmeshnEntity(fid,mName.c_str(),dt,it,MED_CELL,geoTypeReq,MED_NAME,MED_NODAL,&chgt,&trsf);
+  if(nbOfElt>0)
+    {
+      if(!mrs || mrs->isCellNameFieldReading())
+        {
+          namesCells=DataArrayAsciiChar::New();
+          namesCells->alloc(nbOfElt+1,MED_SNAME_SIZE);//not a bug to avoid the memory corruption due to last \0 at the end
+          MEDFILESAFECALLERRD0(MEDmeshEntityNameRd,(fid,mName.c_str(),dt,it,MED_CELL,geoTypeReq,namesCells->getPointer()));
+          namesCells->reAlloc(nbOfElt);//not a bug to avoid the memory corruption due to last \0 at the end
+        }
     }
-  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 std::string& mName, int dt, int it, MEDFileMeshReadSelector *mrs)
 {
   setName(strm->getName());
   setDescription(strm->getDescription());
+  setUnivName(strm->getUnivName());
   setIteration(strm->getIteration());
   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);
+  int nbOfElt(MEDmeshnEntity(fid,mName.c_str(),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());
-    }
-  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->isNodeFamilyFieldReading())
+        {
+          int nbNodes(getNumberOfNodes());
+          if(nbOfElt>nbNodes)
+            throw INTERP_KERNEL::Exception("MEDFileStructuredMesh::loadStrMeshFromFile : invalid size of family node array regarding number of nodes in this ! File seems to be corrupted !");
+          _fam_nodes=DataArrayInt::New();
+          _fam_nodes->alloc(nbNodes,1);//yes nbNodes and not nbOfElt see next line.
+          if(nbNodes>nbOfElt)//yes it appends some times... It explains surely the mdump implementation. Bug revealed by PARAVIS EDF #2475 on structured.med file where only 12 first nodes are !=0 so nbOfElt=12 and nbOfNodes=378...
+            _fam_nodes->fillWithZero();
+          MEDFILESAFECALLERRD0(MEDmeshEntityFamilyNumberRd,(fid,mName.c_str(),dt,it,MED_NODE,MED_NONE,_fam_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);
+  nbOfElt=MEDmeshnEntity(fid,mName.c_str(),dt,it,MED_NODE,MED_NONE,MED_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->isNodeNumFieldReading())
+        {
+          _num_nodes=DataArrayInt::New();
+          _num_nodes->alloc(nbOfElt,1);
+          MEDFILESAFECALLERRD0(MEDmeshEntityNumberRd,(fid,mName.c_str(),dt,it,MED_NODE,MED_NONE,_num_nodes->getPointer()));
+        }
     }
-  nbOfElt=MEDmeshnEntity(fid,mName,dt,it,MED_CELL,geoTypeReq,MED_NUMBER,MED_NODAL,&chgt,&trsf);
+  nbOfElt=MEDmeshnEntity(fid,mName.c_str(),dt,it,MED_NODE,MED_NONE,MED_NAME,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->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
+          MEDFILESAFECALLERRD0(MEDmeshEntityNameRd,(fid,mName.c_str(),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
+        }
     }
+  int meshDim(getStructuredMesh()->getMeshDimension());
+  LoadStrMeshDAFromFile(fid,meshDim,dt,it,mName,mrs,_fam_cells,_num_cells,_names_cells);
+  if(meshDim>=1)
+    LoadStrMeshDAFromFile(fid,meshDim-1,dt,it,mName,mrs,_fam_faces,_num_faces,_names_faces);
 }
 
-void MEDFileStructuredMesh::writeStructuredLL(med_idt fid, const char *maa) const throw(INTERP_KERNEL::Exception)
+void MEDFileStructuredMesh::writeStructuredLL(med_idt fid, const std::string& maa) const
 {
-  int meshDim=getStructuredMesh()->getMeshDimension();
-  med_geometry_type geoTypeReq=GetGeoTypeFromMeshDim(meshDim);
+  int meshDim(getStructuredMesh()->getMeshDimension());
+  med_geometry_type geoTypeReq(GetGeoTypeFromMeshDim(meshDim)),geoTypeReq2(GetGeoTypeFromMeshDim(meshDim-1));
   //
   if((const DataArrayInt *)_fam_cells)
-    MEDmeshEntityFamilyNumberWr(fid,maa,_iteration,_order,MED_CELL,geoTypeReq,_fam_cells->getNumberOfTuples(),_fam_cells->getConstPointer());
+    MEDFILESAFECALLERWR0(MEDmeshEntityFamilyNumberWr,(fid,maa.c_str(),_iteration,_order,MED_CELL,geoTypeReq,_fam_cells->getNumberOfTuples(),_fam_cells->getConstPointer()));
+  if((const DataArrayInt *)_fam_faces)
+    MEDFILESAFECALLERWR0(MEDmeshEntityFamilyNumberWr,(fid,maa.c_str(),_iteration,_order,MED_CELL,geoTypeReq2,_fam_faces->getNumberOfTuples(),_fam_faces->getConstPointer()));
   if((const DataArrayInt *)_fam_nodes)
-    MEDmeshEntityFamilyNumberWr(fid,maa,_iteration,_order,MED_NODE,MED_NONE,_fam_nodes->getNumberOfTuples(),_fam_nodes->getConstPointer());
+    MEDFILESAFECALLERWR0(MEDmeshEntityFamilyNumberWr,(fid,maa.c_str(),_iteration,_order,MED_NODE,MED_NONE,_fam_nodes->getNumberOfTuples(),_fam_nodes->getConstPointer()));
   if((const DataArrayInt *)_num_cells)
-    MEDmeshEntityNumberWr(fid,maa,_iteration,_order,MED_CELL,geoTypeReq,_num_cells->getNumberOfTuples(),_num_cells->getConstPointer());
+    MEDFILESAFECALLERWR0(MEDmeshEntityNumberWr,(fid,maa.c_str(),_iteration,_order,MED_CELL,geoTypeReq,_num_cells->getNumberOfTuples(),_num_cells->getConstPointer()));
+  if((const DataArrayInt *)_num_faces)
+    MEDFILESAFECALLERWR0(MEDmeshEntityNumberWr,(fid,maa.c_str(),_iteration,_order,MED_CELL,geoTypeReq2,_num_faces->getNumberOfTuples(),_num_faces->getConstPointer()));
   if((const DataArrayInt *)_num_nodes)
-    MEDmeshEntityNumberWr(fid,maa,_iteration,_order,MED_NODE,MED_NONE,_num_nodes->getNumberOfTuples(),_num_nodes->getConstPointer());
+    MEDFILESAFECALLERWR0(MEDmeshEntityNumberWr,(fid,maa.c_str(),_iteration,_order,MED_NODE,MED_NONE,_num_nodes->getNumberOfTuples(),_num_nodes->getConstPointer()));
+  if((const DataArrayAsciiChar *)_names_cells)
+    {
+      if(_names_cells->getNumberOfComponents()!=MED_SNAME_SIZE)
+        {
+          std::ostringstream oss; oss << "MEDFileStructuredMesh::writeStructuredLL : expected a name field on cells with number of components set to " << MED_SNAME_SIZE;
+          oss << " ! The array has " << _names_cells->getNumberOfComponents() << " components !";
+          throw INTERP_KERNEL::Exception(oss.str().c_str());
+        }
+      MEDFILESAFECALLERWR0(MEDmeshEntityNameWr,(fid,maa.c_str(),_iteration,_order,MED_CELL,geoTypeReq,_names_cells->getNumberOfTuples(),_names_cells->getConstPointer()));
+    }
+  if((const DataArrayAsciiChar *)_names_faces)
+    {
+      if(_names_faces->getNumberOfComponents()!=MED_SNAME_SIZE)
+        {
+          std::ostringstream oss; oss << "MEDFileStructuredMesh::writeStructuredLL : expected a name field on faces with number of components set to " << MED_SNAME_SIZE;
+          oss << " ! The array has " << _names_faces->getNumberOfComponents() << " components !";
+          throw INTERP_KERNEL::Exception(oss.str().c_str());
+        }
+      MEDFILESAFECALLERWR0(MEDmeshEntityNameWr,(fid,maa.c_str(),_iteration,_order,MED_CELL,geoTypeReq2,_names_faces->getNumberOfTuples(),_names_faces->getConstPointer()));
+    }
+  if((const DataArrayAsciiChar *)_names_nodes)
+    {
+      if(_names_nodes->getNumberOfComponents()!=MED_SNAME_SIZE)
+        {
+          std::ostringstream oss; oss << "MEDFileStructuredMesh::writeStructuredLL : expected a name field on nodes with number of components set to " << MED_SNAME_SIZE;
+          oss << " ! The array has " << _names_cells->getNumberOfComponents() << " components !";
+          throw INTERP_KERNEL::Exception(oss.str().c_str());
+        }
+      MEDFILESAFECALLERWR0(MEDmeshEntityNameWr,(fid,maa.c_str(),_iteration,_order,MED_NODE,MED_NONE,_names_nodes->getNumberOfTuples(),_names_nodes->getConstPointer()));
+    }
   //
-  MEDFileUMeshL2::WriteFamiliesAndGrps(fid,maa,_families,_groups,_too_long_str);
+  MEDFileUMeshL2::WriteFamiliesAndGrps(fid,maa.c_str(),_families,_groups,_too_long_str);
 }
 
+/*!
+ * Returns an empty instance of MEDFileCMesh.
+ *  \return MEDFileCMesh * - a new instance of MEDFileCMesh. The caller is to delete this
+ *          mesh using decrRef() as it is no more needed. 
+ */
 MEDFileCMesh *MEDFileCMesh::New()
 {
   return new MEDFileCMesh;
 }
 
-MEDFileCMesh *MEDFileCMesh::New(const char *fileName) throw(INTERP_KERNEL::Exception)
+/*!
+ * Returns a new MEDFileCMesh holding the mesh data that has been read from a given MED
+ * file. The first mesh in the file is loaded.
+ *  \param [in] fileName - the name of MED file to read.
+ *  \return MEDFileCMesh * - a new instance of MEDFileCMesh. The caller is to delete this
+ *          mesh using decrRef() as it is no more needed. 
+ *  \throw If the file is not readable.
+ *  \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 std::string& fileName, MEDFileMeshReadSelector *mrs)
 {
   std::vector<std::string> ms=MEDLoader::GetMeshNames(fileName);
   if(ms.empty())
@@ -3226,53 +5834,101 @@ MEDFileCMesh *MEDFileCMesh::New(const char *fileName) throw(INTERP_KERNEL::Excep
       throw INTERP_KERNEL::Exception(oss.str().c_str());
     }
   MEDFileUtilities::CheckFileForRead(fileName);
-  MEDFileUtilities::AutoFid fid=MEDfileOpen(fileName,MED_ACC_RDONLY);
+  MEDFileUtilities::AutoFid fid=MEDfileOpen(fileName.c_str(),MED_ACC_RDONLY);
   int dt,it;
   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);
+  MEDFileMeshL2::GetMeshIdFromName(fid,ms.front(),meshType,dt,it,dummy2);
+  return new MEDFileCMesh(fid,ms.front(),dt,it,mrs);
 }
 
-MEDFileCMesh *MEDFileCMesh::New(const char *fileName, const char *mName, int dt, int it) throw(INTERP_KERNEL::Exception)
+/*!
+ * Returns a new MEDFileCMesh holding the mesh data that has been read from a given MED
+ * file. The mesh to load is specified by its name and numbers of a time step and an
+ * iteration.
+ *  \param [in] fileName - the name of MED file to read.
+ *  \param [in] mName - the name of the mesh to read.
+ *  \param [in] dt - the number of a time step.
+ *  \param [in] it - the number of an iteration.
+ *  \return MEDFileCMesh * - a new instance of MEDFileCMesh. The caller is to delete this
+ *          mesh using decrRef() as it is no more needed. 
+ *  \throw If the file is not readable.
+ *  \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 std::string& fileName, const std::string& mName, int dt, int it, MEDFileMeshReadSelector *mrs)
 {
   MEDFileUtilities::CheckFileForRead(fileName);
-  MEDFileUtilities::AutoFid fid=MEDfileOpen(fileName,MED_ACC_RDONLY);
-  return new MEDFileCMesh(fid,mName,dt,it);
+  MEDFileUtilities::AutoFid fid=MEDfileOpen(fileName.c_str(),MED_ACC_RDONLY);
+  return new MEDFileCMesh(fid,mName,dt,it,mrs);
+}
+
+std::size_t MEDFileCMesh::getHeapMemorySizeWithoutChildren() const
+{
+  return MEDFileStructuredMesh::getHeapMemorySizeWithoutChildren();
 }
 
-std::size_t MEDFileCMesh::getHeapMemorySize() const
+std::vector<const BigMemoryObject *> MEDFileCMesh::getDirectChildrenWithNull() const
 {
-  std::size_t ret=MEDFileStructuredMesh::getHeapMemorySize();
-  if((const MEDCouplingCMesh *)_cmesh)
-    ret+=_cmesh->getHeapMemorySize();
+  std::vector<const BigMemoryObject *> ret(MEDFileStructuredMesh::getDirectChildrenWithNull());
+  ret.push_back((const MEDCouplingCMesh *)_cmesh);
   return ret;
 }
 
-int MEDFileCMesh::getMeshDimension() const throw(INTERP_KERNEL::Exception)
+/*!
+ * Returns the dimension on cells in \a this mesh.
+ *  \return int - the mesh dimension.
+ *  \throw If there are no cells in this mesh.
+ */
+int MEDFileCMesh::getMeshDimension() const
 {
   if(!((const MEDCouplingCMesh*)_cmesh))
     throw INTERP_KERNEL::Exception("MEDFileCMesh::getMeshDimension : unable to get meshdimension because no mesh set !");
   return _cmesh->getMeshDimension();
 }
 
+/*!
+ * Returns the dimension on nodes in \a this mesh.
+ *  \return int - the space dimension.
+ *  \throw If there are no cells in this mesh.
+ */
+int MEDFileCMesh::getSpaceDimension() const
+{
+  if(!((const MEDCouplingCMesh*)_cmesh))
+    throw INTERP_KERNEL::Exception("MEDFileCMesh::getSpaceDimension : unable to get spacedimension because no mesh set !");
+  return _cmesh->getSpaceDimension();
+}
+
+/*!
+ * Returns a string describing \a this mesh.
+ *  \return std::string - the mesh information string.
+ */
 std::string MEDFileCMesh::simpleRepr() const
 {
   return MEDFileStructuredMesh::simpleRepr();
 }
 
+/*!
+ * Returns a full textual description of \a this mesh.
+ *  \return std::string - the string holding the mesh description.
+ */
 std::string MEDFileCMesh::advancedRepr() const
 {
   return simpleRepr();
 }
 
-MEDFileMesh *MEDFileCMesh::shallowCpy() const throw(INTERP_KERNEL::Exception)
+MEDFileMesh *MEDFileCMesh::shallowCpy() const
 {
   MEDCouplingAutoRefCountObjectPtr<MEDFileCMesh> ret=new MEDFileCMesh(*this);
   return ret.retn();
 }
 
-MEDFileMesh *MEDFileCMesh::deepCpy() const throw(INTERP_KERNEL::Exception)
+MEDFileMesh *MEDFileCMesh::createNewEmpty() const
+{
+  return new MEDFileCMesh;
+}
+
+MEDFileMesh *MEDFileCMesh::deepCpy() const
 {
   MEDCouplingAutoRefCountObjectPtr<MEDFileCMesh> ret=new MEDFileCMesh(*this);
   if((const MEDCouplingCMesh*)_cmesh)
@@ -3281,6 +5937,13 @@ MEDFileMesh *MEDFileCMesh::deepCpy() const throw(INTERP_KERNEL::Exception)
   return ret.retn();
 }
 
+/*!
+ * Checks if \a this and another mesh are equal.
+ *  \param [in] other - the mesh to compare with.
+ *  \param [in] eps - a precision used to compare real values.
+ *  \param [in,out] what - the string returning description of unequal data.
+ *  \return bool - \c true if the meshes are equal, \c false, else.
+ */
 bool MEDFileCMesh::isEqual(const MEDFileMesh *other, double eps, std::string& what) const
 {
   if(!MEDFileStructuredMesh::isEqual(other,eps,what))
@@ -3312,6 +5975,9 @@ bool MEDFileCMesh::isEqual(const MEDFileMesh *other, double eps, std::string& wh
   return true;
 }
 
+/*!
+ * Clears redundant attributes of incorporated data arrays.
+ */
 void MEDFileCMesh::clearNonDiscrAttributes() const
 {
   MEDFileStructuredMesh::clearNonDiscrAttributes();
@@ -3322,17 +5988,18 @@ MEDFileCMesh::MEDFileCMesh()
 {
 }
 
-MEDFileCMesh::MEDFileCMesh(med_idt fid, const char *mName, int dt, int it) throw(INTERP_KERNEL::Exception)
+MEDFileCMesh::MEDFileCMesh(med_idt fid, const std::string& mName, int dt, int it, MEDFileMeshReadSelector *mrs)
 try
-  {
-    loadCMeshFromFile(fid,mName,dt,it);
-  }
+{
+    loadCMeshFromFile(fid,mName,dt,it,mrs);
+    loadJointsFromFile(fid);
+}
 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 std::string& mName, int dt, int it, MEDFileMeshReadSelector *mrs)
 {
   ParaMEDMEM::MEDCouplingMeshType meshType;
   int dummy0,dummy1;
@@ -3348,9 +6015,13 @@ 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);
 }
 
+/*!
+ * Returns a const pointer to MEDCouplingCMesh held by \a this mesh.
+ *  \return const MEDCouplingCMesh * - a pointer to the held MEDCouplingCMesh.
+ */
 const MEDCouplingCMesh *MEDFileCMesh::getMesh() const
 {
   synchronizeTinyInfoOnLeaves();
@@ -3363,7 +6034,13 @@ const MEDCouplingStructuredMesh *MEDFileCMesh::getStructuredMesh() const
   return _cmesh;
 }
 
-void MEDFileCMesh::setMesh(MEDCouplingCMesh *m) throw(INTERP_KERNEL::Exception)
+/*!
+ * Sets the MEDCouplingCMesh holding the data of \a this mesh.
+ *  \param [in] m - the new MEDCouplingCMesh to refer to.
+ *  \throw If the name or the description of \a this mesh and \a m are not empty and are
+ *         different. 
+ */
+void MEDFileCMesh::setMesh(MEDCouplingCMesh *m)
 {
   dealWithTinyInfo(m);
   if(m)
@@ -3371,7 +6048,7 @@ void MEDFileCMesh::setMesh(MEDCouplingCMesh *m) throw(INTERP_KERNEL::Exception)
   _cmesh=m;
 }
 
-void MEDFileCMesh::writeLL(med_idt fid) const throw(INTERP_KERNEL::Exception)
+void MEDFileCMesh::writeLL(med_idt fid) const
 {
   INTERP_KERNEL::AutoPtr<char> maa=MEDLoaderBase::buildEmptyString(MED_NAME_SIZE);
   INTERP_KERNEL::AutoPtr<char> desc=MEDLoaderBase::buildEmptyString(MED_COMMENT_SIZE);
@@ -3379,8 +6056,7 @@ void MEDFileCMesh::writeLL(med_idt fid) const throw(INTERP_KERNEL::Exception)
   MEDLoaderBase::safeStrCpy(_name.c_str(),MED_NAME_SIZE,maa,_too_long_str);
   MEDLoaderBase::safeStrCpy(_desc_name.c_str(),MED_COMMENT_SIZE,desc,_too_long_str);
   MEDLoaderBase::safeStrCpy(_dt_unit.c_str(),MED_LNAME_SIZE,dtunit,_too_long_str);
-  int spaceDim=_cmesh->getSpaceDimension();
-  int meshDim=_cmesh->getMeshDimension();
+  int spaceDim(_cmesh->getSpaceDimension());
   INTERP_KERNEL::AutoPtr<char> comp=MEDLoaderBase::buildEmptyString(spaceDim*MED_SNAME_SIZE);
   INTERP_KERNEL::AutoPtr<char> unit=MEDLoaderBase::buildEmptyString(spaceDim*MED_SNAME_SIZE);
   for(int i=0;i<spaceDim;i++)
@@ -3391,15 +6067,19 @@ void MEDFileCMesh::writeLL(med_idt fid) const throw(INTERP_KERNEL::Exception)
       MEDLoaderBase::safeStrCpy2(c.c_str(),MED_SNAME_SIZE-1,comp+i*MED_SNAME_SIZE,_too_long_str);//MED_TAILLE_PNOM-1 to avoid to write '\0' on next compo
       MEDLoaderBase::safeStrCpy2(u.c_str(),MED_SNAME_SIZE-1,unit+i*MED_SNAME_SIZE,_too_long_str);//MED_TAILLE_PNOM-1 to avoid to write '\0' on next compo
     }
-  MEDmeshCr(fid,maa,spaceDim,meshDim,MED_STRUCTURED_MESH,desc,dtunit,MED_SORT_DTIT,MED_CARTESIAN,comp,unit);
-  MEDmeshGridTypeWr(fid,maa,MED_CARTESIAN_GRID);
+  MEDFILESAFECALLERWR0(MEDmeshCr,(fid,maa,spaceDim,spaceDim,MED_STRUCTURED_MESH,desc,dtunit,MED_SORT_DTIT,MED_CARTESIAN,comp,unit));
+  MEDFILESAFECALLERWR0(MEDmeshUniversalNameWr,(fid,maa));
+  MEDFILESAFECALLERWR0(MEDmeshGridTypeWr,(fid,maa,MED_CARTESIAN_GRID));
   for(int i=0;i<spaceDim;i++)
     {
       const DataArrayDouble *da=_cmesh->getCoordsAt(i);
-      MEDmeshGridIndexCoordinateWr(fid,maa,_iteration,_order,_time,i+1,da->getNumberOfTuples(),da->getConstPointer());
+      MEDFILESAFECALLERWR0(MEDmeshGridIndexCoordinateWr,(fid,maa,_iteration,_order,_time,i+1,da->getNumberOfTuples(),da->getConstPointer()));
     }
   //
-  MEDFileStructuredMesh::writeStructuredLL(fid,maa);
+  std::string meshName(MEDLoaderBase::buildStringFromFortran(maa,MED_NAME_SIZE));
+  MEDFileStructuredMesh::writeStructuredLL(fid,meshName);
+
+  writeJoints(fid);
 }
 
 void MEDFileCMesh::synchronizeTinyInfoOnLeaves() const
@@ -3407,10 +6087,10 @@ void MEDFileCMesh::synchronizeTinyInfoOnLeaves() const
   const MEDCouplingCMesh *cmesh=_cmesh;
   if(!cmesh)
     return;
-  (const_cast<MEDCouplingCMesh *>(cmesh))->setName(_name.c_str());
-  (const_cast<MEDCouplingCMesh *>(cmesh))->setDescription(_desc_name.c_str());
+  (const_cast<MEDCouplingCMesh *>(cmesh))->setName(_name);
+  (const_cast<MEDCouplingCMesh *>(cmesh))->setDescription(_desc_name);
   (const_cast<MEDCouplingCMesh *>(cmesh))->setTime(_time,_iteration,_order);
-  (const_cast<MEDCouplingCMesh *>(cmesh))->setTimeUnit(_dt_unit.c_str());
+  (const_cast<MEDCouplingCMesh *>(cmesh))->setTimeUnit(_dt_unit);
 }
 
 MEDFileCurveLinearMesh *MEDFileCurveLinearMesh::New()
@@ -3418,7 +6098,7 @@ MEDFileCurveLinearMesh *MEDFileCurveLinearMesh::New()
   return new MEDFileCurveLinearMesh;
 }
 
-MEDFileCurveLinearMesh *MEDFileCurveLinearMesh::New(const char *fileName) throw(INTERP_KERNEL::Exception)
+MEDFileCurveLinearMesh *MEDFileCurveLinearMesh::New(const std::string& fileName, MEDFileMeshReadSelector *mrs)
 {
   std::vector<std::string> ms=MEDLoader::GetMeshNames(fileName);
   if(ms.empty())
@@ -3427,36 +6107,45 @@ MEDFileCurveLinearMesh *MEDFileCurveLinearMesh::New(const char *fileName) throw(
       throw INTERP_KERNEL::Exception(oss.str().c_str());
     }
   MEDFileUtilities::CheckFileForRead(fileName);
-  MEDFileUtilities::AutoFid fid=MEDfileOpen(fileName,MED_ACC_RDONLY);
+  MEDFileUtilities::AutoFid fid=MEDfileOpen(fileName.c_str(),MED_ACC_RDONLY);
   int dt,it;
   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);
+  MEDFileMeshL2::GetMeshIdFromName(fid,ms.front(),meshType,dt,it,dummy2);
+  return new MEDFileCurveLinearMesh(fid,ms.front(),dt,it,mrs);
 }
 
-MEDFileCurveLinearMesh *MEDFileCurveLinearMesh::New(const char *fileName, const char *mName, int dt, int it) throw(INTERP_KERNEL::Exception)
+MEDFileCurveLinearMesh *MEDFileCurveLinearMesh::New(const std::string& fileName, const std::string& mName, int dt, int it, MEDFileMeshReadSelector *mrs)
 {
   MEDFileUtilities::CheckFileForRead(fileName);
-  MEDFileUtilities::AutoFid fid=MEDfileOpen(fileName,MED_ACC_RDONLY);
-  return new MEDFileCurveLinearMesh(fid,mName,dt,it);
+  MEDFileUtilities::AutoFid fid=MEDfileOpen(fileName.c_str(),MED_ACC_RDONLY);
+  return new MEDFileCurveLinearMesh(fid,mName,dt,it,mrs);
+}
+
+std::size_t MEDFileCurveLinearMesh::getHeapMemorySizeWithoutChildren() const
+{
+  return MEDFileStructuredMesh::getHeapMemorySizeWithoutChildren();
 }
 
-std::size_t MEDFileCurveLinearMesh::getHeapMemorySize() const
+std::vector<const BigMemoryObject *> MEDFileCurveLinearMesh::getDirectChildrenWithNull() const
 {
-  std::size_t ret=MEDFileStructuredMesh::getHeapMemorySize();
-  if((const MEDCouplingCurveLinearMesh *)_clmesh)
-    ret+=_clmesh->getHeapMemorySize();
+  std::vector<const BigMemoryObject *> ret(MEDFileStructuredMesh::getDirectChildrenWithNull());
+  ret.push_back((const MEDCouplingCurveLinearMesh *)_clmesh);
   return ret;
 }
 
-MEDFileMesh *MEDFileCurveLinearMesh::shallowCpy() const throw(INTERP_KERNEL::Exception)
+MEDFileMesh *MEDFileCurveLinearMesh::shallowCpy() const
 {
   MEDCouplingAutoRefCountObjectPtr<MEDFileCurveLinearMesh> ret=new MEDFileCurveLinearMesh(*this);
   return ret.retn();
 }
 
-MEDFileMesh *MEDFileCurveLinearMesh::deepCpy() const throw(INTERP_KERNEL::Exception)
+MEDFileMesh *MEDFileCurveLinearMesh::createNewEmpty() const
+{
+  return new MEDFileCurveLinearMesh;
+}
+
+MEDFileMesh *MEDFileCurveLinearMesh::deepCpy() const
 {
   MEDCouplingAutoRefCountObjectPtr<MEDFileCurveLinearMesh> ret=new MEDFileCurveLinearMesh(*this);
   if((const MEDCouplingCurveLinearMesh*)_clmesh)
@@ -3465,7 +6154,7 @@ MEDFileMesh *MEDFileCurveLinearMesh::deepCpy() const throw(INTERP_KERNEL::Except
   return ret.retn();
 }
 
-int MEDFileCurveLinearMesh::getMeshDimension() const throw(INTERP_KERNEL::Exception)
+int MEDFileCurveLinearMesh::getMeshDimension() const
 {
   if(!((const MEDCouplingCurveLinearMesh*)_clmesh))
     throw INTERP_KERNEL::Exception("MEDFileCurveLinearMesh::getMeshDimension : unable to get meshdimension because no mesh set !");
@@ -3524,10 +6213,10 @@ void MEDFileCurveLinearMesh::synchronizeTinyInfoOnLeaves() const
   const MEDCouplingCurveLinearMesh *clmesh=_clmesh;
   if(!clmesh)
     return;
-  (const_cast<MEDCouplingCurveLinearMesh *>(clmesh))->setName(_name.c_str());
-  (const_cast<MEDCouplingCurveLinearMesh *>(clmesh))->setDescription(_desc_name.c_str());
+  (const_cast<MEDCouplingCurveLinearMesh *>(clmesh))->setName(_name);
+  (const_cast<MEDCouplingCurveLinearMesh *>(clmesh))->setDescription(_desc_name);
   (const_cast<MEDCouplingCurveLinearMesh *>(clmesh))->setTime(_time,_iteration,_order);
-  (const_cast<MEDCouplingCurveLinearMesh *>(clmesh))->setTimeUnit(_dt_unit.c_str());
+  (const_cast<MEDCouplingCurveLinearMesh *>(clmesh))->setTimeUnit(_dt_unit);
 }
 
 const MEDCouplingCurveLinearMesh *MEDFileCurveLinearMesh::getMesh() const
@@ -3536,7 +6225,7 @@ const MEDCouplingCurveLinearMesh *MEDFileCurveLinearMesh::getMesh() const
   return _clmesh;
 }
 
-void MEDFileCurveLinearMesh::setMesh(MEDCouplingCurveLinearMesh *m) throw(INTERP_KERNEL::Exception)
+void MEDFileCurveLinearMesh::setMesh(MEDCouplingCurveLinearMesh *m)
 {
   dealWithTinyInfo(m);
   if(m)
@@ -3554,17 +6243,18 @@ MEDFileCurveLinearMesh::MEDFileCurveLinearMesh()
 {
 }
 
-MEDFileCurveLinearMesh::MEDFileCurveLinearMesh(med_idt fid, const char *mName, int dt, int it) throw(INTERP_KERNEL::Exception)
+MEDFileCurveLinearMesh::MEDFileCurveLinearMesh(med_idt fid, const std::string& mName, int dt, int it, MEDFileMeshReadSelector *mrs)
 try
-  {
-    loadCLMeshFromFile(fid,mName,dt,it);
-  }
+{
+    loadCLMeshFromFile(fid,mName,dt,it,mrs);
+    loadJointsFromFile(fid);
+}
 catch(INTERP_KERNEL::Exception& e)
-  {
+{
     throw e;
-  }
+}
 
-void MEDFileCurveLinearMesh::writeLL(med_idt fid) const throw(INTERP_KERNEL::Exception)
+void MEDFileCurveLinearMesh::writeLL(med_idt fid) const
 {
   INTERP_KERNEL::AutoPtr<char> maa=MEDLoaderBase::buildEmptyString(MED_NAME_SIZE);
   INTERP_KERNEL::AutoPtr<char> desc=MEDLoaderBase::buildEmptyString(MED_COMMENT_SIZE);
@@ -3587,17 +6277,21 @@ void MEDFileCurveLinearMesh::writeLL(med_idt fid) const throw(INTERP_KERNEL::Exc
       MEDLoaderBase::safeStrCpy2(c.c_str(),MED_SNAME_SIZE-1,comp+i*MED_SNAME_SIZE,_too_long_str);//MED_TAILLE_PNOM-1 to avoid to write '\0' on next compo
       MEDLoaderBase::safeStrCpy2(u.c_str(),MED_SNAME_SIZE-1,unit+i*MED_SNAME_SIZE,_too_long_str);//MED_TAILLE_PNOM-1 to avoid to write '\0' on next compo
     }
-  MEDmeshCr(fid,maa,spaceDim,meshDim,MED_STRUCTURED_MESH,desc,dtunit,MED_SORT_DTIT,MED_CARTESIAN,comp,unit);
-  MEDmeshGridTypeWr(fid,maa,MED_CURVILINEAR_GRID);
+  MEDFILESAFECALLERWR0(MEDmeshCr,(fid,maa,spaceDim,meshDim,MED_STRUCTURED_MESH,desc,dtunit,MED_SORT_DTIT,MED_CARTESIAN,comp,unit));
+  MEDFILESAFECALLERWR0(MEDmeshUniversalNameWr,(fid,maa));
+  MEDFILESAFECALLERWR0(MEDmeshGridTypeWr,(fid,maa,MED_CURVILINEAR_GRID));
   std::vector<int> nodeGridSt=_clmesh->getNodeGridStructure();
-  MEDmeshGridStructWr(fid,maa,_iteration,_order,_time,&nodeGridSt[0]);
-  
-  MEDmeshNodeCoordinateWr(fid,maa,_iteration,_order,_time,MED_FULL_INTERLACE,coords->getNumberOfTuples(),coords->begin());
+  MEDFILESAFECALLERWR0(MEDmeshGridStructWr,(fid,maa,_iteration,_order,_time,&nodeGridSt[0]));
+
+  MEDFILESAFECALLERWR0(MEDmeshNodeCoordinateWr,(fid,maa,_iteration,_order,_time,MED_FULL_INTERLACE,coords->getNumberOfTuples(),coords->begin()));
   //
-  MEDFileStructuredMesh::writeStructuredLL(fid,maa);
+  std::string meshName(MEDLoaderBase::buildStringFromFortran(maa,MED_NAME_SIZE));
+  MEDFileStructuredMesh::writeStructuredLL(fid,meshName);
+
+  writeJoints(fid);
 }
 
-void MEDFileCurveLinearMesh::loadCLMeshFromFile(med_idt fid, const char *mName, int dt, int it) throw(INTERP_KERNEL::Exception)
+void MEDFileCurveLinearMesh::loadCLMeshFromFile(med_idt fid, const std::string& mName, int dt, int it, MEDFileMeshReadSelector *mrs)
 {
   ParaMEDMEM::MEDCouplingMeshType meshType;
   int dummy0,dummy1;
@@ -3613,7 +6307,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()
@@ -3621,17 +6315,17 @@ MEDFileMeshMultiTS *MEDFileMeshMultiTS::New()
   return new MEDFileMeshMultiTS;
 }
 
-MEDFileMeshMultiTS *MEDFileMeshMultiTS::New(const char *fileName) throw(INTERP_KERNEL::Exception)
+MEDFileMeshMultiTS *MEDFileMeshMultiTS::New(const std::string& fileName)
 {
   return new MEDFileMeshMultiTS(fileName);
 }
 
-MEDFileMeshMultiTS *MEDFileMeshMultiTS::New(const char *fileName, const char *mName) throw(INTERP_KERNEL::Exception)
+MEDFileMeshMultiTS *MEDFileMeshMultiTS::New(const std::string& fileName, const std::string& mName)
 {
   return new MEDFileMeshMultiTS(fileName,mName);
 }
 
-MEDFileMeshMultiTS *MEDFileMeshMultiTS::deepCpy() const throw(INTERP_KERNEL::Exception)
+MEDFileMeshMultiTS *MEDFileMeshMultiTS::deepCpy() const
 {
   MEDCouplingAutoRefCountObjectPtr<MEDFileMeshMultiTS> ret=MEDFileMeshMultiTS::New();
   std::vector< MEDCouplingAutoRefCountObjectPtr<MEDFileMesh> > meshOneTs(_mesh_one_ts.size());
@@ -3643,22 +6337,27 @@ MEDFileMeshMultiTS *MEDFileMeshMultiTS::deepCpy() const throw(INTERP_KERNEL::Exc
   return ret.retn();
 }
 
-std::size_t MEDFileMeshMultiTS::getHeapMemorySize() const
+std::size_t MEDFileMeshMultiTS::getHeapMemorySizeWithoutChildren() const
+{
+  return _mesh_one_ts.capacity()*sizeof(MEDCouplingAutoRefCountObjectPtr<MEDFileMesh>);
+}
+
+std::vector<const BigMemoryObject *> MEDFileMeshMultiTS::getDirectChildrenWithNull() const
 {
-  std::size_t ret=_mesh_one_ts.capacity()*sizeof(MEDCouplingAutoRefCountObjectPtr<MEDFileMesh>);
+  std::vector<const BigMemoryObject *> ret;
   for(std::vector< MEDCouplingAutoRefCountObjectPtr<MEDFileMesh> >::const_iterator it=_mesh_one_ts.begin();it!=_mesh_one_ts.end();it++)
-    ret+=(*it)->getHeapMemorySize();
+    ret.push_back((const MEDFileMesh *)*it);
   return ret;
 }
 
-const char *MEDFileMeshMultiTS::getName() const throw(INTERP_KERNEL::Exception)
+std::string MEDFileMeshMultiTS::getName() const
 {
   if(_mesh_one_ts.empty())
     throw INTERP_KERNEL::Exception("MEDFileMeshMultiTS::getName : no time steps set !");
   return _mesh_one_ts[0]->getName();
 }
 
-void MEDFileMeshMultiTS::setName(const char *newMeshName) throw(INTERP_KERNEL::Exception)
+void MEDFileMeshMultiTS::setName(const std::string& newMeshName)
 {
   std::string oldName(getName());
   std::vector< std::pair<std::string,std::string> > v(1);
@@ -3666,7 +6365,7 @@ void MEDFileMeshMultiTS::setName(const char *newMeshName) throw(INTERP_KERNEL::E
   changeNames(v);
 }
 
-bool MEDFileMeshMultiTS::changeNames(const std::vector< std::pair<std::string,std::string> >& modifTab) throw(INTERP_KERNEL::Exception)
+bool MEDFileMeshMultiTS::changeNames(const std::vector< std::pair<std::string,std::string> >& modifTab)
 {
   bool ret=false;
   for(std::vector< MEDCouplingAutoRefCountObjectPtr<MEDFileMesh> >::iterator it=_mesh_one_ts.begin();it!=_mesh_one_ts.end();it++)
@@ -3678,14 +6377,14 @@ bool MEDFileMeshMultiTS::changeNames(const std::vector< std::pair<std::string,st
   return ret;
 }
 
-MEDFileMesh *MEDFileMeshMultiTS::getOneTimeStep() const throw(INTERP_KERNEL::Exception)
+MEDFileMesh *MEDFileMeshMultiTS::getOneTimeStep() const
 {
   if(_mesh_one_ts.empty())
     throw INTERP_KERNEL::Exception("MEDFileMeshMultiTS::getOneTimeStep : empty time step set !");
   return const_cast<MEDFileMesh *>(static_cast<const MEDFileMesh *>(_mesh_one_ts[0]));
 }
 
-void MEDFileMeshMultiTS::setOneTimeStep(MEDFileMesh *mesh1TimeStep) throw(INTERP_KERNEL::Exception)
+void MEDFileMeshMultiTS::setOneTimeStep(MEDFileMesh *mesh1TimeStep)
 {
   if(!mesh1TimeStep)
     throw INTERP_KERNEL::Exception("MEDFileMeshMultiTS::setOneTimeStep : input pointer should be different from 0 !");
@@ -3695,77 +6394,112 @@ void MEDFileMeshMultiTS::setOneTimeStep(MEDFileMesh *mesh1TimeStep) throw(INTERP
   _mesh_one_ts[0]=mesh1TimeStep;
 }
 
-void MEDFileMeshMultiTS::write(med_idt fid) const throw(INTERP_KERNEL::Exception)
+MEDFileJoints * MEDFileMeshMultiTS::getJoints() const
+{
+  if ( MEDFileMesh* m = getOneTimeStep() )
+    return m->getJoints();
+  return 0;
+}
+
+/*!
+ * \brief Set Joints that are common to all time-stamps
+ */
+void MEDFileMeshMultiTS::setJoints( MEDFileJoints* joints )
+{
+  for(std::vector< MEDCouplingAutoRefCountObjectPtr<MEDFileMesh> >::iterator it=_mesh_one_ts.begin();it!=_mesh_one_ts.end();it++)
+    {
+      (*it)->setJoints( joints );
+    }
+}
+
+void MEDFileMeshMultiTS::write(med_idt fid) const
 {
+  MEDFileJoints *joints(getJoints());
+  bool jointsWritten(false);
+
   for(std::vector< MEDCouplingAutoRefCountObjectPtr<MEDFileMesh> >::const_iterator it=_mesh_one_ts.begin();it!=_mesh_one_ts.end();it++)
     {
+      if ( jointsWritten )
+        const_cast<MEDFileMesh&>(**it).setJoints( 0 );
+      else
+        jointsWritten = true;
+
       (*it)->copyOptionsFrom(*this);
       (*it)->write(fid);
     }
+
+  (const_cast<MEDFileMeshMultiTS*>(this))->setJoints( joints ); // restore joints
 }
 
-void MEDFileMeshMultiTS::write(const char *fileName, int mode) const throw(INTERP_KERNEL::Exception)
+void MEDFileMeshMultiTS::write(const std::string& fileName, int mode) const
 {
   med_access_mode medmod=MEDFileUtilities::TraduceWriteMode(mode);
-  MEDFileUtilities::AutoFid fid=MEDfileOpen(fileName,medmod);
+  MEDFileUtilities::AutoFid fid=MEDfileOpen(fileName.c_str(),medmod);
   std::ostringstream oss; oss << "MEDFileMesh : error on attempt to write in file : \"" << fileName << "\""; 
-  MEDFileUtilities::CheckMEDCode(fid,fid,oss.str().c_str());
+  MEDFileUtilities::CheckMEDCode(fid,fid,oss.str());
   write(fid);
 }
 
-void MEDFileMeshMultiTS::loadFromFile(const char *fileName, const char *mName) throw(INTERP_KERNEL::Exception)
-{//for the moment to be improved
-  _mesh_one_ts.resize(1);
-  _mesh_one_ts[0]=MEDFileMesh::New(fileName,mName,-1,-1);
+void MEDFileMeshMultiTS::loadFromFile(const std::string& fileName, const std::string& mName)
+{
+  MEDFileJoints* joints = 0;
+  if ( !_mesh_one_ts.empty() && getOneTimeStep() )
+    {
+      // joints of mName already read, pass them to MEDFileMesh::New() to prevent repeated reading
+      joints = getOneTimeStep()->getJoints();
+    }
+
+  _mesh_one_ts.clear();  //for the moment to be improved
+  _mesh_one_ts.push_back( MEDFileMesh::New(fileName,mName,-1,-1,0, joints ));
 }
 
 MEDFileMeshMultiTS::MEDFileMeshMultiTS()
 {
 }
 
-MEDFileMeshMultiTS::MEDFileMeshMultiTS(const char *fileName) throw(INTERP_KERNEL::Exception)
+MEDFileMeshMultiTS::MEDFileMeshMultiTS(const std::string& fileName)
 try
-  {
+{
     std::vector<std::string> ms=MEDLoader::GetMeshNames(fileName);
     if(ms.empty())
-    {
-      std::ostringstream oss; oss << "MEDFileUMesh::New : no meshes in file \"" << fileName << "\" !";
-      throw INTERP_KERNEL::Exception(oss.str().c_str());
-    }
+      {
+        std::ostringstream oss; oss << "MEDFileUMesh::New : no meshes in file \"" << fileName << "\" !";
+        throw INTERP_KERNEL::Exception(oss.str().c_str());
+      }
     MEDFileUtilities::CheckFileForRead(fileName);
-    MEDFileUtilities::AutoFid fid=MEDfileOpen(fileName,MED_ACC_RDONLY);
+    MEDFileUtilities::AutoFid fid=MEDfileOpen(fileName.c_str(),MED_ACC_RDONLY);
     int dt,it;
     ParaMEDMEM::MEDCouplingMeshType meshType;
     std::string dummy2;
-    MEDFileMeshL2::GetMeshIdFromName(fid,ms.front().c_str(),meshType,dt,it,dummy2);
-    loadFromFile(fileName,ms.front().c_str());
-  }
+    MEDFileMeshL2::GetMeshIdFromName(fid,ms.front(),meshType,dt,it,dummy2);
+    loadFromFile(fileName,ms.front());
+}
 catch(INTERP_KERNEL::Exception& e)
-  {
+{
     throw e;
-  }
+}
 
-MEDFileMeshMultiTS::MEDFileMeshMultiTS(const char *fileName, const char *mName) throw(INTERP_KERNEL::Exception)
+MEDFileMeshMultiTS::MEDFileMeshMultiTS(const std::string& fileName, const std::string& mName)
 try
-  {
+{
     loadFromFile(fileName,mName);
-  }
+}
 catch(INTERP_KERNEL::Exception& e)
-  {
+{
     throw e;
-  }
+}
 
 MEDFileMeshes *MEDFileMeshes::New()
 {
   return new MEDFileMeshes;
 }
 
-MEDFileMeshes *MEDFileMeshes::New(const char *fileName) throw(INTERP_KERNEL::Exception)
+MEDFileMeshes *MEDFileMeshes::New(const std::string& fileName)
 {
   return new MEDFileMeshes(fileName);
 }
 
-void MEDFileMeshes::write(med_idt fid) const throw(INTERP_KERNEL::Exception)
+void MEDFileMeshes::write(med_idt fid) const
 {
   checkCoherency();
   for(std::vector< MEDCouplingAutoRefCountObjectPtr<MEDFileMeshMultiTS> >::const_iterator it=_meshes.begin();it!=_meshes.end();it++)
@@ -3775,27 +6509,28 @@ void MEDFileMeshes::write(med_idt fid) const throw(INTERP_KERNEL::Exception)
     }
 }
 
-void MEDFileMeshes::write(const char *fileName, int mode) const throw(INTERP_KERNEL::Exception)
+void MEDFileMeshes::write(const std::string& fileName, int mode) const
 {
   med_access_mode medmod=MEDFileUtilities::TraduceWriteMode(mode);
-  MEDFileUtilities::AutoFid fid=MEDfileOpen(fileName,medmod);
+  MEDFileUtilities::AutoFid fid=MEDfileOpen(fileName.c_str(),medmod);
   std::ostringstream oss; oss << "MEDFileMesh : error on attempt to write in file : \"" << fileName << "\""; 
-  MEDFileUtilities::CheckMEDCode(fid,fid,oss.str().c_str());
+  MEDFileUtilities::CheckMEDCode(fid,fid,oss.str());
   checkCoherency();
   write(fid);
 }
 
-int MEDFileMeshes::getNumberOfMeshes() const throw(INTERP_KERNEL::Exception)
+int MEDFileMeshes::getNumberOfMeshes() const
 {
   return _meshes.size();
 }
 
-MEDFileMeshesIterator *MEDFileMeshes::iterator() throw(INTERP_KERNEL::Exception)
+MEDFileMeshesIterator *MEDFileMeshes::iterator()
 {
   return new MEDFileMeshesIterator(this);
 }
 
-MEDFileMesh *MEDFileMeshes::getMeshAtPos(int i) const throw(INTERP_KERNEL::Exception)
+/** Return a borrowed reference (caller is not responsible) */
+MEDFileMesh *MEDFileMeshes::getMeshAtPos(int i) const
 {
   if(i<0 || i>=(int)_meshes.size())
     {
@@ -3805,7 +6540,8 @@ MEDFileMesh *MEDFileMeshes::getMeshAtPos(int i) const throw(INTERP_KERNEL::Excep
   return _meshes[i]->getOneTimeStep();
 }
 
-MEDFileMesh *MEDFileMeshes::getMeshWithName(const char *mname) const throw(INTERP_KERNEL::Exception)
+/** Return a borrowed reference (caller is not responsible) */
+MEDFileMesh *MEDFileMeshes::getMeshWithName(const std::string& mname) const
 {
   std::vector<std::string> ms=getMeshesNames();
   std::vector<std::string>::iterator it=std::find(ms.begin(),ms.end(),mname);
@@ -3818,7 +6554,7 @@ MEDFileMesh *MEDFileMeshes::getMeshWithName(const char *mname) const throw(INTER
   return getMeshAtPos((int)std::distance(ms.begin(),it));
 }
 
-std::vector<std::string> MEDFileMeshes::getMeshesNames() const throw(INTERP_KERNEL::Exception)
+std::vector<std::string> MEDFileMeshes::getMeshesNames() const
 {
   std::vector<std::string> ret(_meshes.size());
   int i=0;
@@ -3837,8 +6573,18 @@ std::vector<std::string> MEDFileMeshes::getMeshesNames() const throw(INTERP_KERN
     }
   return ret;
 }
+/*const MEDFileJoints* MEDFileMeshes::getJoints() const
+{
+  const MEDFileJoints *ret=_joints;
+  if(!ret)
+  {
+    std::ostringstream oss; oss << "MEDFileMeshes::getJoints : joints is not defined !";
+    throw INTERP_KERNEL::Exception(oss.str().c_str());
+  }
+  return ret;
+}*/
 
-bool MEDFileMeshes::changeNames(const std::vector< std::pair<std::string,std::string> >& modifTab) throw(INTERP_KERNEL::Exception)
+bool MEDFileMeshes::changeNames(const std::vector< std::pair<std::string,std::string> >& modifTab)
 {
   bool ret=false;
   for(std::vector< MEDCouplingAutoRefCountObjectPtr<MEDFileMeshMultiTS> >::iterator it=_meshes.begin();it!=_meshes.end();it++)
@@ -3850,12 +6596,12 @@ bool MEDFileMeshes::changeNames(const std::vector< std::pair<std::string,std::st
   return ret;
 }
 
-void MEDFileMeshes::resize(int newSize) throw(INTERP_KERNEL::Exception)
+void MEDFileMeshes::resize(int newSize)
 {
   _meshes.resize(newSize);
 }
 
-void MEDFileMeshes::pushMesh(MEDFileMesh *mesh) throw(INTERP_KERNEL::Exception)
+void MEDFileMeshes::pushMesh(MEDFileMesh *mesh)
 {
   if(!mesh)
     throw INTERP_KERNEL::Exception("MEDFileMeshes::pushMesh : invalid input pointer ! should be different from 0 !");
@@ -3864,7 +6610,7 @@ void MEDFileMeshes::pushMesh(MEDFileMesh *mesh) throw(INTERP_KERNEL::Exception)
   _meshes.push_back(elt);
 }
 
-void MEDFileMeshes::setMeshAtPos(int i, MEDFileMesh *mesh) throw(INTERP_KERNEL::Exception)
+void MEDFileMeshes::setMeshAtPos(int i, MEDFileMesh *mesh)
 {
   if(!mesh)
     throw INTERP_KERNEL::Exception("MEDFileMeshes::setMeshAtPos : invalid input pointer ! should be different from 0 !");
@@ -3875,7 +6621,7 @@ void MEDFileMeshes::setMeshAtPos(int i, MEDFileMesh *mesh) throw(INTERP_KERNEL::
   _meshes[i]=elt;
 }
 
-void MEDFileMeshes::destroyMeshAtPos(int i) throw(INTERP_KERNEL::Exception)
+void MEDFileMeshes::destroyMeshAtPos(int i)
 {
   if(i<0 || i>=(int)_meshes.size())
     {
@@ -3885,29 +6631,29 @@ void MEDFileMeshes::destroyMeshAtPos(int i) throw(INTERP_KERNEL::Exception)
   _meshes.erase(_meshes.begin()+i);
 }
 
-void MEDFileMeshes::loadFromFile(const char *fileName) throw(INTERP_KERNEL::Exception)
+void MEDFileMeshes::loadFromFile(const std::string& fileName)
 {
   std::vector<std::string> ms=MEDLoader::GetMeshNames(fileName);
   int i=0;
   _meshes.resize(ms.size());
   for(std::vector<std::string>::const_iterator it=ms.begin();it!=ms.end();it++,i++)
-    _meshes[i]=MEDFileMeshMultiTS::New(fileName,(*it).c_str());
+    _meshes[i]=MEDFileMeshMultiTS::New(fileName,(*it));
 }
 
 MEDFileMeshes::MEDFileMeshes()
 {
 }
 
-MEDFileMeshes::MEDFileMeshes(const char *fileName) throw(INTERP_KERNEL::Exception)
+MEDFileMeshes::MEDFileMeshes(const std::string& fileName)
 try
-  {
+{
     loadFromFile(fileName);
-  }
-catch(INTERP_KERNEL::Exception& e)
-  {
-  }
+}
+catch(INTERP_KERNEL::Exception& /*e*/)
+{
+}
 
-MEDFileMeshes *MEDFileMeshes::deepCpy() const throw(INTERP_KERNEL::Exception)
+MEDFileMeshes *MEDFileMeshes::deepCpy() const
 {
   std::vector< MEDCouplingAutoRefCountObjectPtr<MEDFileMeshMultiTS> > meshes(_meshes.size());
   std::size_t i=0;
@@ -3919,13 +6665,17 @@ MEDFileMeshes *MEDFileMeshes::deepCpy() const throw(INTERP_KERNEL::Exception)
   return ret.retn();
 }
 
-std::size_t MEDFileMeshes::getHeapMemorySize() const
+std::size_t MEDFileMeshes::getHeapMemorySizeWithoutChildren() const
 {
-  std::size_t ret=_meshes.capacity()*(sizeof(MEDCouplingAutoRefCountObjectPtr<MEDFileMeshMultiTS>));
+  return _meshes.capacity()*(sizeof(MEDCouplingAutoRefCountObjectPtr<MEDFileMeshMultiTS>));
+}
+
+std::vector<const BigMemoryObject *> MEDFileMeshes::getDirectChildrenWithNull() const
+{
+  std::vector<const BigMemoryObject *> ret;
   for(std::vector< MEDCouplingAutoRefCountObjectPtr<MEDFileMeshMultiTS> >::const_iterator it=_meshes.begin();it!=_meshes.end();it++)
-    if((const MEDFileMeshMultiTS*)*it)
-      ret+=(*it)->getHeapMemorySize();
-  return ret; 
+    ret.push_back((const MEDFileMeshMultiTS *)*it);
+  return ret;
 }
 
 std::string MEDFileMeshes::simpleRepr() const
@@ -3945,7 +6695,7 @@ void MEDFileMeshes::simpleReprWithoutHeader(std::ostream& oss) const
     oss << "  - #" << i << " \"" << mns[i] << "\"\n";
 }
 
-void MEDFileMeshes::checkCoherency() const throw(INTERP_KERNEL::Exception)
+void MEDFileMeshes::checkCoherency() const
 {
   static const char MSG[]="MEDFileMeshes::checkCoherency : mesh at rank ";
   int i=0;