Salome HOME
Merge branch 'abn/seg_seg_intersec'
[tools/medcoupling.git] / src / MEDLoader / MEDFileMesh.cxx
index 24b61d534b62e914044f01ba6ef06a7371d85368..7e610d1a8117bebc5c6b0851899f72caa7f499dc 100644 (file)
@@ -513,7 +513,7 @@ std::vector<std::string> MEDFileMesh::getFamiliesNames() const
  * Returns names of all families of \a this mesh but like they would be in file.
  * This method is here only for MED file families gurus. If you are a kind user forget this method :-)
  * This method is only useful for aggressive users that want to have in their file a same family lying both on cells and on nodes. This is not a good idea for lisibility !
- * For your information internaly in memory such families are renamed to have a nicer API.
+ * For your information internally in memory such families are renamed to have a nicer API.
  */
 std::vector<std::string> MEDFileMesh::getFamiliesNamesWithFilePointOfView() const
 {
@@ -673,6 +673,35 @@ std::vector<std::string> MEDFileMesh::removeEmptyGroups()
   return ret;
 }
 
+void MEDFileMesh::removeGroupAtLevel(int meshDimRelToMaxExt, const std::string& name)
+{
+  std::map<std::string, std::vector<std::string> >::iterator it(_groups.find(name));
+  std::vector<std::string> grps(getGroupsNames());
+  if(it==_groups.end())
+    {
+      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());
+    }
+  const std::vector<std::string> &famsOnGrp((*it).second);
+  std::vector<int> famIds(getFamiliesIdsOnGroup(name));
+  const DataArrayInt *famArr(getFamilyFieldAtLevel(meshDimRelToMaxExt));
+  if(!famArr)
+    return ;
+  MCAuto<DataArrayInt> vals(famArr->getDifferentValues());
+  MCAuto<DataArrayInt> famIds2(DataArrayInt::NewFromStdVector(famIds));
+  MCAuto<DataArrayInt> idsToKill(famIds2->buildIntersection(vals));
+  if(idsToKill->empty())
+    return ;
+  std::vector<std::string> newFamsOnGrp;
+  for(std::vector<std::string>::const_iterator it=famsOnGrp.begin();it!=famsOnGrp.end();it++)
+    {
+      if(!idsToKill->presenceOfValue(getFamilyId(*it)))
+         newFamsOnGrp.push_back(*it);
+    }
+  (*it).second=newFamsOnGrp;
+}
+
 /*!
  * Removes a group from \a this mesh.
  *  \param [in] name - the name of the group to remove.
@@ -680,9 +709,8 @@ std::vector<std::string> MEDFileMesh::removeEmptyGroups()
  */
 void MEDFileMesh::removeGroup(const std::string& name)
 {
-  std::string oname(name);
-  std::map<std::string, std::vector<std::string> >::iterator it=_groups.find(oname);
-  std::vector<std::string> grps=getGroupsNames();
+  std::map<std::string, std::vector<std::string> >::iterator it=_groups.find(name);
+  std::vector<std::string> grps(getGroupsNames());
   if(it==_groups.end())
     {
       std::ostringstream oss; oss << "No such groupname \"" << name << "\" !\nAvailable groups are :";
@@ -795,7 +823,7 @@ void MEDFileMesh::removeFamiliesReferedByNoGroups()
 }
 
 /*!
- * 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
+ * This method has no impact on groups. This method only works on families. This method firstly removes families not referred 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.
  *
@@ -1256,6 +1284,19 @@ void MEDFileMesh::addFamilyOnAllGroupsHaving(const std::string& famName, const s
     }
 }
 
+void MEDFileMesh::checkNoGroupClash(const DataArrayInt *famArr, const std::string& grpName) const
+{
+  std::vector<std::string> grpsNames(getGroupsNames());
+  if(std::find(grpsNames.begin(),grpsNames.end(),grpName)==grpsNames.end())
+    return ;
+  std::vector<int> famIds(getFamiliesIdsOnGroup(grpName));
+  if(famArr->presenceOfValue(famIds))
+    {
+      std::ostringstream oss; oss << "MEDFileUMesh::addGroup : Group with name \"" << grpName << "\" already exists at specified level ! Destroy it before calling this method !";
+      throw INTERP_KERNEL::Exception(oss.str().c_str());
+    }
+}
+
 /*!
  * \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)
@@ -1268,13 +1309,8 @@ void MEDFileMesh::addGroupUnderground(bool isNodeGroup, const DataArrayInt *ids,
   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(); MCAuto<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());
-    }
+  checkNoGroupClash(famArr,grpName);
+  MCAuto<DataArrayInt> famArrTmp; famArrTmp.takeRef(famArr);
   std::list< MCAuto<DataArrayInt> > allFamIds(getAllNonNullFamilyIds());
   allFamIds.erase(std::find(allFamIds.begin(),allFamIds.end(),famArrTmp));
   MCAuto<DataArrayInt> famIds=famArr->selectByTupleIdSafe(ids->begin(),ids->end());
@@ -1331,8 +1367,15 @@ void MEDFileMesh::addGroupUnderground(bool isNodeGroup, const DataArrayInt *ids,
       famArr->setPartOfValuesSimple3(familyIds[i],da->begin(),da->end(),0,1,1);
     }
   _families=families;
+  std::map<std::string, std::vector<std::string> >::iterator itt(groups.find(grpName));
+  if(itt!=groups.end())
+    {
+      std::vector<std::string>& famsOnGrp((*itt).second);
+      famsOnGrp.insert(famsOnGrp.end(),fams.begin(),fams.end());
+    }
+  else
+    groups[grpName]=fams;
   _groups=groups;
-  _groups[grpName]=fams;
 }
 
 void MEDFileMesh::changeAllGroupsContainingFamily(const std::string& familyNameToChange, const std::vector<std::string>& newFamiliesNames)
@@ -2282,7 +2325,7 @@ MEDFileUMesh *MEDFileUMesh::New(med_idt fid, MEDFileMeshReadSelector *mrs)
 }
 
 /*!
- * \b WARNING this implementation is dependant from MEDCouplingMappedExtrudedMesh::buildUnstructured !
+ * \b WARNING this implementation is dependent from MEDCouplingMappedExtrudedMesh::buildUnstructured !
  * \sa MEDCouplingMappedExtrudedMesh::buildUnstructured , MEDCouplingMappedExtrudedMesh::build3DUnstructuredMesh
  */
 MEDFileUMesh *MEDFileUMesh::New(const MEDCouplingMappedExtrudedMesh *mem)
@@ -2347,7 +2390,7 @@ MEDFileUMesh *MEDFileUMesh::LoadPartOf(med_idt fid, const std::string& mName, co
 std::size_t MEDFileUMesh::getHeapMemorySizeWithoutChildren() const
 {
   std::size_t ret(MEDFileMesh::getHeapMemorySizeWithoutChildren());
-  ret+=_ms.capacity()*(sizeof(MCAuto<MEDFileUMeshSplitL1>));
+  ret+=_ms.capacity()*(sizeof(MCAuto<MEDFileUMeshSplitL1>))+_elt_str.capacity()*sizeof(MCAuto<MEDFileEltStruct4Mesh>);
   return ret;
 }
 
@@ -2357,11 +2400,14 @@ std::vector<const BigMemoryObject *> MEDFileUMesh::getDirectChildrenWithNull() c
   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 *)_global_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< MCAuto<MEDFileUMeshSplitL1> >::const_iterator it=_ms.begin();it!=_ms.end();it++)
     ret.push_back((const MEDFileUMeshSplitL1*) *it);
+  for(std::vector< MCAuto<MEDFileEltStruct4Mesh> >::const_iterator it=_elt_str.begin();it!=_elt_str.end();it++)
+    ret.push_back((const MEDFileEltStruct4Mesh *)*it);
   return ret;
 }
 
@@ -2380,15 +2426,17 @@ MEDFileUMesh *MEDFileUMesh::deepCopy() const
 {
   MCAuto<MEDFileUMesh> ret(new MEDFileUMesh(*this));
   ret->deepCpyEquivalences(*this);
-  if((const DataArrayDouble*)_coords)
+  if(_coords.isNotNull())
     ret->_coords=_coords->deepCopy();
-  if((const DataArrayInt*)_fam_coords)
+  if(_fam_coords.isNotNull())
     ret->_fam_coords=_fam_coords->deepCopy();
-  if((const DataArrayInt*)_num_coords)
+  if(_num_coords.isNotNull())
     ret->_num_coords=_num_coords->deepCopy();
-  if((const DataArrayInt*)_rev_num_coords)
+  if(_global_num_coords.isNotNull())
+    ret->_global_num_coords=_global_num_coords->deepCopy();
+  if(_rev_num_coords.isNotNull())
     ret->_rev_num_coords=_rev_num_coords->deepCopy();
-  if((const DataArrayAsciiChar*)_name_coords)
+  if(_name_coords.isNotNull())
     ret->_name_coords=_name_coords->deepCopy();
   std::size_t i=0;
   for(std::vector< MCAuto<MEDFileUMeshSplitL1> >::const_iterator it=_ms.begin();it!=_ms.end();it++,i++)
@@ -2436,54 +2484,74 @@ bool MEDFileUMesh::isEqual(const MEDFileMesh *other, double eps, std::string& wh
           return false;
         }
     }
-  const DataArrayInt *famc1=_fam_coords;
-  const DataArrayInt *famc2=otherC->_fam_coords;
-  if((famc1==0 && famc2!=0) || (famc1!=0 && famc2==0))
-    {
-      what="Mismatch of families arr on nodes ! One is defined and not other !";
-      return false;
-    }
-  if(famc1)
-    {
-      bool ret=famc1->isEqual(*famc2);
-      if(!ret)
-        {
-          what="Families arr on node differ !";
-          return false;
-        }
-    }
-  const DataArrayInt *numc1=_num_coords;
-  const DataArrayInt *numc2=otherC->_num_coords;
-  if((numc1==0 && numc2!=0) || (numc1!=0 && numc2==0))
-    {
-      what="Mismatch of numbering arr on nodes ! One is defined and not other !";
-      return false;
-    }
-  if(numc1)
-    {
-      bool ret=numc1->isEqual(*numc2);
-      if(!ret)
-        {
-          what="Numbering arr on node differ !";
-          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;
-        }
-    }
+  {
+    const DataArrayInt *famc1(_fam_coords),*famc2(otherC->_fam_coords);
+    if((famc1==0 && famc2!=0) || (famc1!=0 && famc2==0))
+      {
+        what="Mismatch of families arr on nodes ! One is defined and not other !";
+        return false;
+      }
+    if(famc1)
+      {
+        bool ret=famc1->isEqual(*famc2);
+        if(!ret)
+          {
+            what="Families arr on node differ !";
+            return false;
+          }
+      }
+  }
+  {
+    const DataArrayInt *numc1(_num_coords),*numc2(otherC->_num_coords);
+    if((numc1==0 && numc2!=0) || (numc1!=0 && numc2==0))
+      {
+        what="Mismatch of numbering arr on nodes ! One is defined and not other !";
+        return false;
+      }
+    if(numc1)
+      {
+        bool ret=numc1->isEqual(*numc2);
+        if(!ret)
+          {
+            what="Numbering arr on node differ !";
+            return false;
+          }
+      }
+  }
+  {
+    const DataArrayInt *gnumc1(_global_num_coords),*gnumc2(otherC->_global_num_coords);
+    if((gnumc1==0 && gnumc2!=0) || (gnumc1!=0 && gnumc2==0))
+      {
+        what="Mismatch of numbering arr on nodes ! One is defined and not other !";
+        return false;
+      }
+    if(gnumc1)
+      {
+        bool ret=gnumc1->isEqual(*gnumc2);
+        if(!ret)
+          {
+            what="Global numbering arr on node differ !";
+            return false;
+          }
+      }
+  }
+  {
+    const DataArrayAsciiChar *namec1(_name_coords),*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 !";
@@ -2532,15 +2600,15 @@ void MEDFileUMesh::checkConsistency() const
         throw INTERP_KERNEL::Exception("MEDFileUMesh::checkConsistency(): coords are null but some mesh parts are present!");
       if (!_fam_coords)
         throw INTERP_KERNEL::Exception("MEDFileUMesh::checkConsistency(): coords are null but not the internal node family array!");
-      if (!_num_coords || !_rev_num_coords)
+      if (_num_coords.isNotNull() || _rev_num_coords.isNotNull() || _global_num_coords.isNotNull())
         throw INTERP_KERNEL::Exception("MEDFileUMesh::checkConsistency(): coords are null but not the internal node numbering array!");
     }
   else
     {
       int nbCoo = _coords->getNumberOfTuples();
-      if (_fam_coords)
+      if (_fam_coords.isNotNull())
         _fam_coords->checkNbOfTuplesAndComp(nbCoo,1,"MEDFileUMesh::checkConsistency(): inconsistent internal node family array!");
-      if (_num_coords)
+      if (_num_coords.isNotNull())
         {
           _num_coords->checkNbOfTuplesAndComp(nbCoo,1,"MEDFileUMesh::checkConsistency(): inconsistent internal node numbering array!");
           int pos;
@@ -2548,6 +2616,10 @@ void MEDFileUMesh::checkConsistency() const
           if (!_rev_num_coords || _rev_num_coords->getNumberOfTuples() != (maxValue+1))
             throw INTERP_KERNEL::Exception("MEDFileUMesh::checkConsistency(): inconsistent internal revert node numbering array!");
         }
+      if (_global_num_coords.isNotNull())
+        {
+          _global_num_coords->checkNbOfTuplesAndComp(nbCoo,1,"MEDFileUMesh::checkConsistency(): inconsistent global node numbering array!");
+        }
       if ((_num_coords && !_rev_num_coords) || (!_num_coords && _rev_num_coords))
         throw INTERP_KERNEL::Exception("MEDFileUMesh::checkConsistency(): inconsistent internal numbering arrays (one is null)!");
       if (_num_coords && !_num_coords->hasUniqueValues())
@@ -2598,13 +2670,14 @@ void MEDFileUMesh::checkSMESHConsistency() const
  */
 void MEDFileUMesh::clearNodeAndCellNumbers()
 {
-  _num_coords = 0;
-  _rev_num_coords = 0;
-  for (std::vector< MCAuto<MEDFileUMeshSplitL1> >::iterator it=_ms.begin();
-      it != _ms.end(); it++)
+  _num_coords.nullify();
+  _rev_num_coords.nullify();
+  _global_num_coords.nullify();
+  for (std::vector< MCAuto<MEDFileUMeshSplitL1> >::iterator it=_ms.begin(); it != _ms.end(); it++)
     {
-      (*it)->_num = 0;
-      (*it)->_rev_num = 0;
+      (*it)->_num.nullify();
+      (*it)->_rev_num.nullify();
+      (*it)->_global_num.nullify();
     }
 }
 
@@ -2614,30 +2687,25 @@ void MEDFileUMesh::clearNodeAndCellNumbers()
 void MEDFileUMesh::clearNonDiscrAttributes() const
 {
   MEDFileMesh::clearNonDiscrAttributes();
-  const DataArrayDouble *coo1=_coords;
-  if(coo1)
-    (const_cast<DataArrayDouble *>(coo1))->setName("");//This parameter is not discriminant for comparison
-  const DataArrayInt *famc1=_fam_coords;
-  if(famc1)
-    (const_cast<DataArrayInt *>(famc1))->setName("");//This parameter is not discriminant for comparison
-  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
+  if(_coords.isNotNull())
+    _coords.iAmATrollConstCast()->setName("");//This parameter is not discriminant for comparison
+  if(_fam_coords.isNotNull())
+    _fam_coords.iAmATrollConstCast()->setName("");//This parameter is not discriminant for comparison
+  if(_num_coords.isNotNull())
+    _num_coords.iAmATrollConstCast()->setName("");//This parameter is not discriminant for comparison
+  if(_name_coords.isNotNull())
+    _name_coords.iAmATrollConstCast()->setName("");//This parameter is not discriminant for comparison
   for(std::vector< MCAuto<MEDFileUMeshSplitL1> >::const_iterator it=_ms.begin();it!=_ms.end();it++)
     {
-      const MEDFileUMeshSplitL1 *tmp=(*it);
-      if(tmp)
-        tmp->clearNonDiscrAttributes();
+      if((*it).isNotNull())
+        (*it)->clearNonDiscrAttributes();
     }
 }
 
 void MEDFileUMesh::setName(const std::string& name)
 {
   for(std::vector< MCAuto<MEDFileUMeshSplitL1> >::iterator it=_ms.begin();it!=_ms.end();it++)
-    if((MEDFileUMeshSplitL1 *)(*it)!=0)
+    if((*it).isNotNull())
       (*it)->setName(name);
   MEDFileMesh::setName(name);
 }
@@ -2751,7 +2819,7 @@ void MEDFileMesh::checkCartesian() const
   if(getAxisType()!=AX_CART)
     {
       std::ostringstream oss; oss << "MEDFileMesh::checkCartesian : request for method that is dedicated to a cartesian convention ! But you are not in cartesian convention (" << DataArray::GetAxisTypeRepr(getAxisType()) << ").";
-      oss << std::endl << "To perform operation you have two possiblities :" << std::endl;
+      oss << std::endl << "To perform operation you have two possibilities :" << std::endl;
       oss << " - call setAxisType(AX_CART)" << std::endl;
       oss << " - call cartesianize()";
       throw INTERP_KERNEL::Exception(oss.str().c_str());
@@ -2805,6 +2873,17 @@ void MEDFileUMesh::loadLL(med_idt fid, const std::string& mName, int dt, int it,
     }
   loaderl2.loadAll(fid,mid,mName,dt,it,mrs);
   dispatchLoadedPart(fid,loaderl2,mName,mrs);
+  // Structure element part...
+  int nModels(-1);
+  {
+    med_bool chgt=MED_FALSE,trsf=MED_FALSE;
+    nModels=MEDmeshnEntity(fid,mName.c_str(),dt,it,MED_STRUCT_ELEMENT,MED_GEO_ALL,MED_CONNECTIVITY,MED_NODAL,&chgt,&trsf);
+  }
+  if(nModels<=0)
+    return ;
+  _elt_str.resize(nModels);
+  for(int i=0;i<nModels;i++)
+    _elt_str[i]=MEDFileEltStruct4Mesh::New(fid,mName,dt,it,i,mrs);
 }
 
 void MEDFileUMesh::dispatchLoadedPart(med_idt fid, const MEDFileUMeshL2& loaderl2, const std::string& mName, MEDFileMeshReadSelector *mrs)
@@ -2834,6 +2913,8 @@ void MEDFileUMesh::dispatchLoadedPart(med_idt fid, const MEDFileUMeshL2& loaderl
     _num_coords=loaderl2.getCoordsNum();
   if(!mrs || mrs->isNodeNameFieldReading())
     _name_coords=loaderl2.getCoordsName();
+  if(!mrs || mrs->isGlobalNodeNumFieldReading())
+    _global_num_coords=loaderl2.getCoordsGlobalNum();
   _part_coords=loaderl2.getPartDefOfCoo();
   computeRevNum();
 }
@@ -2867,7 +2948,7 @@ void MEDFileUMesh::writeMeshLL(med_idt fid) const
   if(_univ_wr_status)
     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);
+  MEDFileUMeshL2::WriteCoords(fid,meshName,_iteration,_order,_time,_coords,_fam_coords,_num_coords,_name_coords,_global_num_coords);
   for(std::vector< MCAuto<MEDFileUMeshSplitL1> >::const_iterator it=_ms.begin();it!=_ms.end();it++)
     if((const MEDFileUMeshSplitL1 *)(*it)!=0)
       (*it)->write(fid,meshName,mdim);
@@ -2926,8 +3007,7 @@ std::vector<int> MEDFileUMesh::getFamArrNonEmptyLevelsExt() const
 std::vector<int> MEDFileUMesh::getNumArrNonEmptyLevelsExt() const
 {
   std::vector<int> ret;
-  const DataArrayInt *numCoo(_num_coords);
-  if(numCoo)
+  if(_num_coords.isNotNull())
     ret.push_back(1);
   int lev=0;
   for(std::vector< MCAuto<MEDFileUMeshSplitL1> >::const_iterator it=_ms.begin();it!=_ms.end();it++,lev--)
@@ -3217,6 +3297,13 @@ const DataArrayAsciiChar *MEDFileUMesh::getNameFieldAtLevel(int meshDimRelToMaxE
   return l1->getNameField();
 }
 
+MCAuto<DataArrayInt> MEDFileUMesh::getGlobalNumFieldAtLevel(int meshDimRelToMaxExt) const
+{
+  if(meshDimRelToMaxExt!=1)
+    throw INTERP_KERNEL::Exception("MEDFileUMesh::getGlobalNumFieldAtLevel : not implemented yet for structured mesh !");
+  return _global_num_coords;
+}
+
 /*!
  * 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).
  *
@@ -3301,6 +3388,19 @@ MEDFileMesh *MEDFileUMesh::cartesianize() const
     }
 }
 
+bool MEDFileUMesh::presenceOfStructureElements() const
+{
+  for(std::vector< MCAuto<MEDFileEltStruct4Mesh> >::const_iterator it=_elt_str.begin();it!=_elt_str.end();it++)
+    if((*it).isNotNull())
+      return true;
+  return false;
+}
+
+void MEDFileUMesh::killStructureElements()
+{
+  _elt_str.clear();
+}
+
 /*!
  * Returns the optional numbers of mesh entities of a given dimension transformed using
  * DataArrayInt::invertArrayN2O2O2N().
@@ -3313,11 +3413,11 @@ const DataArrayInt *MEDFileUMesh::getRevNumberFieldAtLevel(int meshDimRelToMaxEx
 {
   if(meshDimRelToMaxExt==1)
     {
-      if(!((const DataArrayInt *)_num_coords))
+      if(_num_coords.isNull())
         throw INTERP_KERNEL::Exception("MEDFileUMesh::getRevNumberFieldAtLevel : no coordinates renum specified !");
       return _rev_num_coords;
     }
-  const MEDFileUMeshSplitL1 *l1=getMeshAtLevSafe(meshDimRelToMaxExt);
+  const MEDFileUMeshSplitL1 *l1(getMeshAtLevSafe(meshDimRelToMaxExt));
   return l1->getRevNumberField();
 }
 
@@ -3578,7 +3678,7 @@ MEDCouplingUMesh *MEDFileUMesh::getLevelM3Mesh(bool renum) const
 /*!
  * 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.
+ * When assignment 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
@@ -3758,12 +3858,11 @@ void MEDFileUMesh::setCoords(DataArrayDouble *coords)
     return ;
   coords->checkAllocated();
   int nbOfTuples(coords->getNumberOfTuples());
-  _coords=coords;
-  coords->incrRef();
+  _coords.takeRef(coords);
   _fam_coords=DataArrayInt::New();
   _fam_coords->alloc(nbOfTuples,1);
   _fam_coords->fillWithZero();
-  _num_coords=0; _rev_num_coords=0; _name_coords=0;
+  _num_coords.nullify(); _rev_num_coords.nullify(); _name_coords.nullify(); _global_num_coords.nullify();
   for(std::vector< MCAuto<MEDFileUMeshSplitL1> >::iterator it=_ms.begin();it!=_ms.end();it++)
     if((MEDFileUMeshSplitL1 *)(*it))
       (*it)->setCoords(coords);
@@ -3888,7 +3987,7 @@ void MEDFileUMesh::buildInnerBoundaryAlongM1Group(const std::string& grpNameM1,
 
   std::vector<int> levs=getNonEmptyLevels();
   if(std::find(levs.begin(),levs.end(),0)==levs.end() || std::find(levs.begin(),levs.end(),-1)==levs.end())
-    throw INTERP_KERNEL::Exception("MEDFileUMesh::buildInnerBoundaryAlongM1Group : This method works only for mesh definied on level 0 and -1 !");
+    throw INTERP_KERNEL::Exception("MEDFileUMesh::buildInnerBoundaryAlongM1Group : This method works only for mesh defined on level 0 and -1 !");
   MUMesh m0=getMeshAtLevel(0);
   MUMesh m1=getMeshAtLevel(-1);
   int nbNodes=m0->getNumberOfNodes();
@@ -3981,8 +4080,8 @@ void MEDFileUMesh::buildInnerBoundaryAlongM1Group(const std::string& grpNameM1,
       _fam_coords=newFam;
     }
 
-  _num_coords = 0;
-  _rev_num_coords = 0;
+  _num_coords.nullify(); _rev_num_coords.nullify(); _global_num_coords.nullify();
+  
   for (std::vector< MCAuto<MEDFileUMeshSplitL1> >::iterator it=_ms.begin();
       it != _ms.end(); it++)
     {
@@ -4077,12 +4176,12 @@ struct MEDLoaderAccVisit1
 /*! \endcond */
 
 /*!
- * Array returned is the correspondance in \b old \b to \b new format. The returned array is newly created and should be dealt by the caller.
+ * Array returned is the correspondence in \b old \b to \b new format. The returned array is newly created and should be dealt by the caller.
  * The maximum value stored in returned array is the number of nodes of \a this minus 1 after call of this method.
  * 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 \c NULL pointer is returned and nothing
+ * \return newly allocated array containing correspondence 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.
@@ -4122,12 +4221,14 @@ DataArrayInt *MEDFileUMesh::zipCoords()
   MCAuto<DataArrayAsciiChar> newNameCoords;
   if((const DataArrayInt *)_fam_coords)
     newFamCoords=_fam_coords->selectByTupleIdSafe(ret2->begin(),ret2->end());
-  MCAuto<DataArrayInt> newNumCoords;
-  if((const DataArrayInt *)_num_coords)
+  MCAuto<DataArrayInt> newNumCoords,newGlobalNumCoords;
+  if(_num_coords.isNotNull())
     newNumCoords=_num_coords->selectByTupleIdSafe(ret2->begin(),ret2->end());
-  if((const DataArrayAsciiChar *)_name_coords)
+  if(_global_num_coords.isNotNull())
+    newGlobalNumCoords=_global_num_coords->selectByTupleIdSafe(ret2->begin(),ret2->end());
+  if(_name_coords.isNotNull())
     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;
+  _coords=newCoords; _fam_coords=newFamCoords; _num_coords=newNumCoords; _global_num_coords=newGlobalNumCoords; _name_coords=newNameCoords; _rev_num_coords.nullify();
   for(std::vector< MCAuto<MEDFileUMeshSplitL1> >::iterator it=_ms.begin();it!=_ms.end();it++)
     {
       if((MEDFileUMeshSplitL1*)*it)
@@ -4816,7 +4917,7 @@ void MEDFileUMesh::addNodeGroup(const DataArrayInt *ids)
   if(!coords)
     throw INTERP_KERNEL::Exception("MEDFileUMesh::addNodeGroup : no coords set !");
   int nbOfNodes(coords->getNumberOfTuples());
-  if(!((DataArrayInt *)_fam_coords))
+  if(_fam_coords.isNull())
     { _fam_coords=DataArrayInt::New(); _fam_coords->alloc(nbOfNodes,1); _fam_coords->fillWithZero(); }
   //
   addGroupUnderground(true,ids,_fam_coords);
@@ -4947,7 +5048,7 @@ MCAuto<MEDFileUMeshSplitL1>& MEDFileUMesh::checkAndGiveEntryInSplitL1(int meshDi
  *
  * \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.
+ *                     If false, an exception is thrown. If true the mesh is reordered automatically. It is highly recommended to let this parameter to false.
  *
  * \throw If \a there is a null pointer in \a ms.
  * \sa MEDFileUMesh::setMeshAtLevel
@@ -5116,8 +5217,7 @@ void MEDFileUMesh::setFamilyFieldArr(int meshDimRelToMaxExt, DataArrayInt *famAr
       if(!coo)
         throw INTERP_KERNEL::Exception("MEDFileUMesh::setFamilyFieldArr : the coordinates have not been set !");
       famArr->checkNbOfTuplesAndComp(coo->getNumberOfTuples(),1,"MEDFileUMesh::setFamilyFieldArr : Problem in size of node family arr ! ");
-      famArr->incrRef();
-      _fam_coords=famArr;
+      _fam_coords.takeRef(famArr);
       return ;
     }
   if(meshDimRelToMaxExt>1)
@@ -5143,16 +5243,14 @@ void MEDFileUMesh::setRenumFieldArr(int meshDimRelToMaxExt, DataArrayInt *renumA
     {
       if(!renumArr)
         {
-          _num_coords=0;
-          _rev_num_coords=0;
+          _num_coords.nullify();
+          _rev_num_coords.nullify();
           return ;
         }
-      DataArrayDouble *coo(_coords);
-      if(!coo)
+      if(_coords.isNull())
         throw INTERP_KERNEL::Exception("MEDFileUMesh::setRenumFieldArr : the coordinates have not been set !");
-      renumArr->checkNbOfTuplesAndComp(coo->getNumberOfTuples(),1,"MEDFileUMesh::setRenumArr : Problem in size of node numbering arr ! ");
-      renumArr->incrRef();
-      _num_coords=renumArr;
+      renumArr->checkNbOfTuplesAndComp(_coords->getNumberOfTuples(),1,"MEDFileUMesh::setRenumArr : Problem in size of node numbering arr ! ");
+      _num_coords.takeRef(renumArr);
       computeRevNum();
       return ;
     }
@@ -5186,8 +5284,7 @@ void MEDFileUMesh::setNameFieldAtLevel(int meshDimRelToMaxExt, DataArrayAsciiCha
       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;
+      _name_coords.takeRef(nameArr);
       return ;
     }
   if(meshDimRelToMaxExt>1)
@@ -5200,6 +5297,15 @@ void MEDFileUMesh::setNameFieldAtLevel(int meshDimRelToMaxExt, DataArrayAsciiCha
   return _ms[traducedRk]->setNameArr(nameArr);
 }
 
+void MEDFileUMesh::setGlobalNumFieldAtLevel(int meshDimRelToMaxExt, DataArrayInt *globalNumArr)
+{
+  if(meshDimRelToMaxExt!=1)
+    throw INTERP_KERNEL::Exception("MEDFileUMesh::setGlobalNumFieldAtLevel : Only implemented for meshDimRelToMaxExt==1 for the moment !");
+  if(globalNumArr)
+    globalNumArr->checkNbOfTuplesAndComp(_coords->getNumberOfTuples(),1,"MEDFileUMesh::setGlobalNumFieldAtLevel : Problem in size of node global numbering arr ! ");
+  _global_num_coords.takeRef(globalNumArr);
+}
+
 void MEDFileUMesh::synchronizeTinyInfoOnLeaves() const
 {
   for(std::vector< MCAuto<MEDFileUMeshSplitL1> >::const_iterator it=_ms.begin();it!=_ms.end();it++)
@@ -5246,7 +5352,7 @@ std::list< MCAuto<DataArrayInt> > MEDFileUMesh::getAllNonNullFamilyIds() const
 
 void MEDFileUMesh::computeRevNum() const
 {
-  if((const DataArrayInt *)_num_coords)
+  if(_num_coords.isNotNull())
     {
       int pos;
       int maxValue=_num_coords->getMaxValue(pos);
@@ -5728,6 +5834,11 @@ void MEDFileStructuredMesh::setNameFieldAtLevel(int meshDimRelToMaxExt, DataArra
     nameArr->incrRef();
 }
 
+void MEDFileStructuredMesh::setGlobalNumFieldAtLevel(int meshDimRelToMaxExt, DataArrayInt *globalNumArr)
+{
+  throw INTERP_KERNEL::Exception("MEDFileStructuredMesh::setGlobalNumFieldAtLevel : not implemented yet !");
+}
+
 /*!
  * Adds a group of nodes to \a this mesh.
  *  \param [in] ids - a DataArrayInt providing ids and a name of the group to add.
@@ -5889,6 +6000,11 @@ const DataArrayAsciiChar *MEDFileStructuredMesh::getNameFieldAtLevel(int meshDim
   }
 }
 
+MCAuto<DataArrayInt> MEDFileStructuredMesh::getGlobalNumFieldAtLevel(int meshDimRelToMaxExt) const
+{
+  throw INTERP_KERNEL::Exception("MEDFileStructuredMesh::getGlobalNumFieldAtLevel : not implemented yet for structured mesh !");
+}
+
 /*!
  * Returns relative dimensions of mesh entities (excluding nodes) present in \a this mesh.
  *  \return std::vector<int> - a sequence of the relative dimensions: [0].
@@ -6022,7 +6138,7 @@ void MEDFileStructuredMesh::deepCpyAttributes()
 }
 
 /*!
- * Returns a pointer to mesh at the specified level (here 0 is compulsary for cartesian mesh).
+ * Returns a pointer to mesh at the specified level (here 0 is compulsory for cartesian mesh).
  * 
  * \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.
@@ -7080,6 +7196,22 @@ void MEDFileMeshMultiTS::setJoints( MEDFileJoints* joints )
     }
 }
 
+bool MEDFileMeshMultiTS::presenceOfStructureElements() const
+{
+  for(std::vector< MCAuto<MEDFileMesh> >::const_iterator it=_mesh_one_ts.begin();it!=_mesh_one_ts.end();it++)
+    if((*it).isNotNull())
+      if((*it)->presenceOfStructureElements())
+        return true;
+  return false;
+}
+
+void MEDFileMeshMultiTS::killStructureElements()
+{
+  for(std::vector< MCAuto<MEDFileMesh> >::iterator it=_mesh_one_ts.begin();it!=_mesh_one_ts.end();it++)
+    if((*it).isNotNull())
+      (*it)->killStructureElements();
+}
+
 void MEDFileMeshMultiTS::writeLL(med_idt fid) const
 {
   MEDFileJoints *joints(getJoints());
@@ -7373,6 +7505,22 @@ void MEDFileMeshes::checkConsistencyLight() const
     }
 }
 
+bool MEDFileMeshes::presenceOfStructureElements() const
+{
+  for(std::vector< MCAuto<MEDFileMeshMultiTS> >::const_iterator it=_meshes.begin();it!=_meshes.end();it++)
+    if((*it).isNotNull())
+      if((*it)->presenceOfStructureElements())
+        return true;
+  return false;
+}
+
+void MEDFileMeshes::killStructureElements()
+{
+  for(std::vector< MCAuto<MEDFileMeshMultiTS> >::iterator it=_meshes.begin();it!=_meshes.end();it++)
+    if((*it).isNotNull())
+      (*it)->killStructureElements();
+}
+
 MEDFileMeshesIterator::MEDFileMeshesIterator(MEDFileMeshes *ms):_ms(ms),_iter_id(0),_nb_iter(0)
 {
   if(ms)
@@ -7400,13 +7548,33 @@ MEDFileMesh *MEDFileMeshesIterator::nextt()
     return 0;
 }
 
-INTERP_KERNEL::NormalizedCellType MEDFileMesh::ConvertFromMEDFile(med_geometry_type geoType)
+INTERP_KERNEL::NormalizedCellType MEDFileMesh::ConvertFromMEDFileGeoType(med_geometry_type geoType)
 {
   med_geometry_type *pos(std::find(typmai,typmai+MED_N_CELL_FIXED_GEO,geoType));
   if(pos==typmai+MED_N_CELL_FIXED_GEO)
     {
-      std::ostringstream oss; oss << "MEDFileMesh::ConvertFromMEDFile : no entry with " << geoType << " !"; 
+      if(geoType==MED_NO_GEOTYPE)
+        return INTERP_KERNEL::NORM_ERROR;
+      std::ostringstream oss; oss << "MEDFileMesh::ConvertFromMEDFileGeoType : no entry with " << geoType << " !"; 
       throw INTERP_KERNEL::Exception(oss.str());
     }
   return typmai2[std::distance(typmai,pos)];
 }
+
+TypeOfField MEDFileMesh::ConvertFromMEDFileEntity(med_entity_type etype)
+{
+  switch(etype)
+    {
+    case MED_NODE:
+      return ON_NODES;
+    case MED_CELL:
+      return ON_CELLS;
+    default:
+      {
+        std::ostringstream oss; oss << "EDFileMesh::ConvertFromMEDFileEntity : not recognized entity " << etype << " !";
+        throw INTERP_KERNEL::Exception(oss.str());
+      }
+    }
+}
+
+