Salome HOME
23298: EDF 13271 SMESH: ExportMED fails
[modules/smesh.git] / src / DriverMED / DriverMED_W_SMESHDS_Mesh.cxx
index f5370662b8c79d07566f61206a240e6992369f86..f31f262c03438b16bd4bcd561a227484f13ab973 100644 (file)
@@ -1,43 +1,48 @@
-//  SMESH DriverMED : driver to read and write 'med' files
+// Copyright (C) 2007-2016  CEA/DEN, EDF R&D, OPEN CASCADE
 //
-//  Copyright (C) 2003  OPEN CASCADE, EADS/CCR, LIP6, CEA/DEN,
-//  CEDRAT, EDF R&D, LEG, PRINCIPIA R&D, BUREAU VERITAS 
-// 
-//  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. 
-// 
-//  This library is distributed in the hope that it will be useful, 
-//  but WITHOUT ANY WARRANTY; without even the implied warranty of 
-//  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU 
-//  Lesser General Public License for more details. 
-// 
-//  You should have received a copy of the GNU Lesser General Public 
-//  License along with this library; if not, write to the Free Software 
-//  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA 
-// 
-// See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com
+// Copyright (C) 2003-2007  OPEN CASCADE, EADS/CCR, LIP6, CEA/DEN,
+// CEDRAT, EDF R&D, LEG, PRINCIPIA R&D, BUREAU VERITAS
+//
+// 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, 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
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+// Lesser General Public License for more details.
 //
+// You should have received a copy of the GNU Lesser General Public
+// License along with this library; if not, write to the Free Software
+// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA
 //
+// See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com
+//
+
+//  SMESH DriverMED : driver to read and write 'med' files
 //  File   : DriverMED_W_SMESHDS_Mesh.cxx
 //  Module : SMESH
-
-#include <sstream>
+//
 
 #include "DriverMED_W_SMESHDS_Mesh.h"
-#include "DriverMED_W_SMDS_Mesh.h"
-#include "DriverMED_Family.h"
 
-#include "SMESHDS_Mesh.hxx"
+#include "DriverMED_Family.h"
+#include "MED_Factory.hxx"
+#include "MED_Utilities.hxx"
+#include "SMDS_IteratorOnIterators.hxx"
 #include "SMDS_MeshElement.hxx"
 #include "SMDS_MeshNode.hxx"
 #include "SMDS_PolyhedralVolumeOfNodes.hxx"
+#include "SMDS_SetIterator.hxx"
+#include "SMESHDS_Mesh.hxx"
 
-#include "utilities.h"
+#include <BRep_Tool.hxx>
+#include <TopExp_Explorer.hxx>
+#include <TopoDS.hxx>
+
+#include <utilities.h>
 
-#include "MED_Utilities.hxx"
 
 #define _EDF_NODE_IDS_
 //#define _ELEMENTS_BY_DIM_
@@ -47,32 +52,37 @@ using namespace MED;
 
 
 DriverMED_W_SMESHDS_Mesh::DriverMED_W_SMESHDS_Mesh():
+  myMedVersion(MED::eV2_2),
   myAllSubMeshes (false),
   myDoGroupOfNodes (false),
   myDoGroupOfEdges (false),
   myDoGroupOfFaces (false),
-  myDoGroupOfVolumes (false)
+  myDoGroupOfVolumes (false),
+  myDoGroupOf0DElems(false),
+  myDoGroupOfBalls(false),
+  myAutoDimension(false),
+  myAddODOnVertices(false)
 {}
 
 void DriverMED_W_SMESHDS_Mesh::SetFile(const std::string& theFileName, 
-                                      MED::EVersion theId)
+                                       MED::EVersion      theId)
 {
-  myMed = CrWrapper(theFileName,theId);
   Driver_SMESHDS_Mesh::SetFile(theFileName);
+  myMedVersion = theId;
 }
 
 void DriverMED_W_SMESHDS_Mesh::SetFile(const std::string& theFileName)
 {
-  return SetFile(theFileName,MED::eV2_2);
+  Driver_SMESHDS_Mesh::SetFile(theFileName);
 }
 
 string DriverMED_W_SMESHDS_Mesh::GetVersionString(const MED::EVersion theVersion, int theNbDigits)
 {
   TInt majeur, mineur, release;
   majeur =  mineur = release = 0;
-  if ( theVersion == eV2_1 )
-    MED::GetVersionRelease<eV2_1>(majeur, mineur, release);
-  else
+//   if ( theVersion == eV2_1 )
+//     MED::GetVersionRelease<eV2_1>(majeur, mineur, release);
+//   else
     MED::GetVersionRelease<eV2_2>(majeur, mineur, release);
   ostringstream name;
   if ( theNbDigits > 0 )
@@ -84,11 +94,6 @@ string DriverMED_W_SMESHDS_Mesh::GetVersionString(const MED::EVersion theVersion
   return name.str();
 }
 
-void DriverMED_W_SMESHDS_Mesh::SetMeshName(const std::string& theMeshName)
-{
-  myMeshName = theMeshName;
-}
-
 void DriverMED_W_SMESHDS_Mesh::AddGroup(SMESHDS_GroupBase* theGroup)
 {
   myGroups.push_back(theGroup);
@@ -101,7 +106,7 @@ void DriverMED_W_SMESHDS_Mesh::AddAllSubMeshes()
 
 void DriverMED_W_SMESHDS_Mesh::AddSubMesh(SMESHDS_SubMesh* theSubMesh, int theID)
 {
-  mySubMeshes[theID] = theSubMesh;
+  mySubMeshes.push_back( theSubMesh );
 }
 
 void DriverMED_W_SMESHDS_Mesh::AddGroupOfNodes()
@@ -124,7 +129,8 @@ void DriverMED_W_SMESHDS_Mesh::AddGroupOfVolumes()
   myDoGroupOfVolumes = true;
 }
 
-namespace{
+namespace
+{
   typedef double (SMDS_MeshNode::* TGetCoord)() const;
   typedef const char* TName;
   typedef const char* TUnit;
@@ -190,9 +196,9 @@ namespace{
     TUnit* myUnit;
   public:
     TCoordHelper(const SMDS_NodeIteratorPtr& theNodeIter,
-                TGetCoord* theGetCoord,
-                TName* theName,
-                TUnit* theUnit = aUnit):
+                 TGetCoord* theGetCoord,
+                 TName* theName,
+                 TUnit* theUnit = aUnit):
       myNodeIter(theNodeIter),
       myGetCoord(theGetCoord),
       myName(theName),
@@ -201,7 +207,7 @@ namespace{
     virtual ~TCoordHelper(){}
     bool Next(){ 
       return myNodeIter->more() && 
-       (myCurrentNode = myNodeIter->next());
+        (myCurrentNode = myNodeIter->next());
     }
     const SMDS_MeshNode* GetNode(){
       return myCurrentNode;
@@ -220,10 +226,89 @@ namespace{
     }
   };
   typedef boost::shared_ptr<TCoordHelper> TCoordHelperPtr;
-  
+
+  //-------------------------------------------------------
+  /*!
+   * \brief Structure describing element type
+   */
+  //-------------------------------------------------------
+  struct TElemTypeData
+  {
+    EEntiteMaillage     _entity;
+    EGeometrieElement   _geomType;
+    TInt                _nbElems;
+    SMDSAbs_ElementType _smdsType;
+
+    TElemTypeData (EEntiteMaillage entity, EGeometrieElement geom, TInt nb, SMDSAbs_ElementType type)
+      : _entity(entity), _geomType(geom), _nbElems( nb ), _smdsType( type ) {}
+  };
+
+
+  typedef NCollection_DataMap< Standard_Address, int > TElemFamilyMap;
+
+  //================================================================================
+  /*!
+   * \brief Fills element to famaly ID map for element type.
+   * Removes all families of anElemType
+   */
+  //================================================================================
+
+  void fillElemFamilyMap( TElemFamilyMap &            anElemFamMap,
+                          list<DriverMED_FamilyPtr> & aFamilies,
+                          const SMDSAbs_ElementType   anElemType)
+  {
+    anElemFamMap.Clear();
+    list<DriverMED_FamilyPtr>::iterator aFamsIter = aFamilies.begin();
+    while ( aFamsIter != aFamilies.end() )
+    {
+      if ((*aFamsIter)->GetType() != anElemType) {
+        aFamsIter++;
+      }
+      else {
+        int aFamId = (*aFamsIter)->GetId();
+        const ElementsSet&              anElems = (*aFamsIter)->GetElements();
+        ElementsSet::const_iterator anElemsIter = anElems.begin();
+        for (; anElemsIter != anElems.end(); anElemsIter++)
+        {
+          anElemFamMap.Bind( (Standard_Address)*anElemsIter, aFamId );
+        }
+        // remove a family from the list
+        aFamilies.erase( aFamsIter++ );
+      }
+    }
+  }
+
+  //================================================================================
+  /*!
+   * \brief For an element, return family ID found in the map or a default one
+   */
+  //================================================================================
+
+  int getFamilyId( const TElemFamilyMap &  anElemFamMap,
+                   const SMDS_MeshElement* anElement,
+                   const int               aDefaultFamilyId)
+  {
+    if ( anElemFamMap.IsBound( (Standard_Address) anElement ))
+      return anElemFamMap( (Standard_Address) anElement );
+
+    return aDefaultFamilyId;
+  }
+
+  //================================================================================
+  /*!
+   * \brief Returns iterator on sub-meshes
+   */
+  //================================================================================
+
+  SMESHDS_SubMeshIteratorPtr getIterator( std::vector<SMESHDS_SubMesh*>& mySubMeshes )
+  {
+    return SMESHDS_SubMeshIteratorPtr
+      ( new SMDS_SetIterator
+        < const SMESHDS_SubMesh*, std::vector< SMESHDS_SubMesh* >::iterator >( mySubMeshes.begin(),
+                                                                               mySubMeshes.end() ));
+  }
 }
 
-  
 Driver_Mesh::Status DriverMED_W_SMESHDS_Mesh::Perform()
 {
   Status aResult = DRS_OK;
@@ -231,8 +316,8 @@ Driver_Mesh::Status DriverMED_W_SMESHDS_Mesh::Perform()
     INFOS("SMDS_MESH with hasConstructionEdges() or hasConstructionFaces() do not supports!!!");
     return DRS_FAIL;
   }
-  try{
-    MESSAGE("Perform - myFile : "<<myFile);
+  try {
+    //MESSAGE("Perform - myFile : "<<myFile);
 
     // Creating the MED mesh for corresponding SMDS structure
     //-------------------------------------------------------
@@ -246,103 +331,132 @@ Driver_Mesh::Status DriverMED_W_SMESHDS_Mesh::Perform()
     }
 
     // Mesh dimension definition
-    TInt aMeshDimension;
+
+    TInt aMeshDimension = 0;
+    if ( myMesh->NbEdges() > 0 )
+      aMeshDimension = 1;
+    if ( myMesh->NbFaces() > 0 )
+      aMeshDimension = 2;
+    if ( myMesh->NbVolumes() > 0 )
+      aMeshDimension = 3;
+
+    TInt aSpaceDimension = 3;
     TCoordHelperPtr aCoordHelperPtr;
-    {  
+    {
       bool anIsXDimension = false;
       bool anIsYDimension = false;
       bool anIsZDimension = false;
+      if ( myAutoDimension && aMeshDimension < 3 )
       {
-       SMDS_NodeIteratorPtr aNodesIter = myMesh->nodesIterator();
-       double aBounds[6];
-       if(aNodesIter->more()){
-         const SMDS_MeshNode* aNode = aNodesIter->next();
-         aBounds[0] = aBounds[1] = aNode->X();
-         aBounds[2] = aBounds[3] = aNode->Y();
-         aBounds[4] = aBounds[5] = aNode->Z();
-       }
-       while(aNodesIter->more()){
-         const SMDS_MeshNode* aNode = aNodesIter->next();
-         aBounds[0] = min(aBounds[0],aNode->X());
-         aBounds[1] = max(aBounds[1],aNode->X());
-         
-         aBounds[2] = min(aBounds[2],aNode->Y());
-         aBounds[3] = max(aBounds[3],aNode->Y());
-         
-         aBounds[4] = min(aBounds[4],aNode->Z());
-         aBounds[5] = max(aBounds[5],aNode->Z());
-       }
-
-       double EPS = 1.0E-7;
-       anIsXDimension = (aBounds[1] - aBounds[0]) + abs(aBounds[1]) + abs(aBounds[0]) > EPS;
-       anIsYDimension = (aBounds[3] - aBounds[2]) + abs(aBounds[3]) + abs(aBounds[2]) > EPS;
-       anIsZDimension = (aBounds[5] - aBounds[4]) + abs(aBounds[5]) + abs(aBounds[4]) > EPS;
-       aMeshDimension = anIsXDimension + anIsYDimension + anIsZDimension;
-       if(!aMeshDimension)
-         aMeshDimension = 3;
+        SMDS_NodeIteratorPtr aNodesIter = myMesh->nodesIterator();
+        double aBounds[6];
+        if(aNodesIter->more()){
+          const SMDS_MeshNode* aNode = aNodesIter->next();
+          aBounds[0] = aBounds[1] = aNode->X();
+          aBounds[2] = aBounds[3] = aNode->Y();
+          aBounds[4] = aBounds[5] = aNode->Z();
+        }
+        while(aNodesIter->more()){
+          const SMDS_MeshNode* aNode = aNodesIter->next();
+          aBounds[0] = min(aBounds[0],aNode->X());
+          aBounds[1] = max(aBounds[1],aNode->X());
+          
+          aBounds[2] = min(aBounds[2],aNode->Y());
+          aBounds[3] = max(aBounds[3],aNode->Y());
+
+          aBounds[4] = min(aBounds[4],aNode->Z());
+          aBounds[5] = max(aBounds[5],aNode->Z());
+        }
+
+        double EPS = 1.0E-7;
+        TopoDS_Shape mainShape = myMesh->ShapeToMesh();
+        bool    hasShapeToMesh = ( myMesh->SubMeshIndices().size() > 1 );
+        if ( !mainShape.IsNull() && hasShapeToMesh )
+        {
+          // define EPS by max tolerance of the mainShape (IPAL53097)
+          TopExp_Explorer subShape;
+          for ( subShape.Init( mainShape, TopAbs_FACE ); subShape.More(); subShape.Next() ) {
+            EPS = Max( EPS, BRep_Tool::Tolerance( TopoDS::Face( subShape.Current() )));
+          }
+          for ( subShape.Init( mainShape, TopAbs_EDGE ); subShape.More(); subShape.Next() ) {
+            EPS = Max( EPS, BRep_Tool::Tolerance( TopoDS::Edge( subShape.Current() )));
+          }
+          for ( subShape.Init( mainShape, TopAbs_VERTEX ); subShape.More(); subShape.Next() ) {
+            EPS = Max( EPS, BRep_Tool::Tolerance( TopoDS::Vertex( subShape.Current() )));
+          }
+          EPS *= 2.;
+        }
+        anIsXDimension = (aBounds[1] - aBounds[0]) + abs(aBounds[1]) + abs(aBounds[0]) > EPS;
+        anIsYDimension = (aBounds[3] - aBounds[2]) + abs(aBounds[3]) + abs(aBounds[2]) > EPS;
+        anIsZDimension = (aBounds[5] - aBounds[4]) + abs(aBounds[5]) + abs(aBounds[4]) > EPS;
+        aSpaceDimension = Max( aMeshDimension, anIsXDimension + anIsYDimension + anIsZDimension );
+        if ( !aSpaceDimension )
+          aSpaceDimension = 3;
         // PAL16857(SMESH not conform to the MED convention):
-        if ( aMeshDimension == 2 && anIsZDimension ) // 2D only if mesh is in XOY plane
-          aMeshDimension = 3;
+        if ( aSpaceDimension == 2 && anIsZDimension ) // 2D only if mesh is in XOY plane
+          aSpaceDimension = 3;
         // PAL18941(a saved study with a mesh belong Z is opened and the mesh is belong X)
-        if ( aMeshDimension == 1 && !anIsXDimension ) // 1D only if mesh is along OX
+        if ( aSpaceDimension == 1 && !anIsXDimension ) {// 1D only if mesh is along OX
           if ( anIsYDimension ) {
-            aMeshDimension = 2;
+            aSpaceDimension = 2;
             anIsXDimension = true;
           } else {
-            aMeshDimension = 3;
+            aSpaceDimension = 3;
           }
+        }
       }
 
-      SMDS_NodeIteratorPtr aNodesIter = myMesh->nodesIterator();
-      switch(aMeshDimension){
+      SMDS_NodeIteratorPtr aNodesIter = myMesh->nodesIterator(/*idInceasingOrder=*/true);
+      switch ( aSpaceDimension ) {
       case 3:
-       aCoordHelperPtr.reset(new TCoordHelper(aNodesIter,aXYZGetCoord,aXYZName));
-       break;
+        aCoordHelperPtr.reset(new TCoordHelper(aNodesIter,aXYZGetCoord,aXYZName));
+        break;
       case 2:
-       if(anIsXDimension && anIsYDimension)
-         aCoordHelperPtr.reset(new TCoordHelper(aNodesIter,aXYGetCoord,aXYName));
-       if(anIsYDimension && anIsZDimension)
-         aCoordHelperPtr.reset(new TCoordHelper(aNodesIter,aYZGetCoord,aYZName));
-       if(anIsXDimension && anIsZDimension)
-         aCoordHelperPtr.reset(new TCoordHelper(aNodesIter,aXZGetCoord,aXZName));
-       break;
+        if(anIsXDimension && anIsYDimension)
+          aCoordHelperPtr.reset(new TCoordHelper(aNodesIter,aXYGetCoord,aXYName));
+        if(anIsYDimension && anIsZDimension)
+          aCoordHelperPtr.reset(new TCoordHelper(aNodesIter,aYZGetCoord,aYZName));
+        if(anIsXDimension && anIsZDimension)
+          aCoordHelperPtr.reset(new TCoordHelper(aNodesIter,aXZGetCoord,aXZName));
+        break;
       case 1:
-       if(anIsXDimension)
-         aCoordHelperPtr.reset(new TCoordHelper(aNodesIter,aXGetCoord,aXName));
-       if(anIsYDimension)
-         aCoordHelperPtr.reset(new TCoordHelper(aNodesIter,aYGetCoord,aYName));
-       if(anIsZDimension)
-         aCoordHelperPtr.reset(new TCoordHelper(aNodesIter,aZGetCoord,aZName));
-       break;
+        if(anIsXDimension)
+          aCoordHelperPtr.reset(new TCoordHelper(aNodesIter,aXGetCoord,aXName));
+        if(anIsYDimension)
+          aCoordHelperPtr.reset(new TCoordHelper(aNodesIter,aYGetCoord,aYName));
+        if(anIsZDimension)
+          aCoordHelperPtr.reset(new TCoordHelper(aNodesIter,aZGetCoord,aZName));
+        break;
       }
     }
-
     
-    PMeshInfo aMeshInfo = myMed->CrMeshInfo(aMeshDimension,aMeshName);
-    MESSAGE("Add - aMeshName : "<<aMeshName<<"; "<<aMeshInfo->GetName());
+    MED::PWrapper myMed = CrWrapper(myFile,myMedVersion);
+    PMeshInfo aMeshInfo = myMed->CrMeshInfo(aMeshDimension,aSpaceDimension,aMeshName);
+    //MESSAGE("Add - aMeshName : "<<aMeshName<<"; "<<aMeshInfo->GetName());
     myMed->SetMeshInfo(aMeshInfo);
 
-    // Storing SMDS groups and sub-meshes
-    //-----------------------------------
-    int myNodesDefaultFamilyId   = 0;
-    int myEdgesDefaultFamilyId   = 0;
-    int myFacesDefaultFamilyId   = 0;
-    int myVolumesDefaultFamilyId = 0;
-    int nbNodes   = myMesh->NbNodes();
-    int nbEdges   = myMesh->NbEdges();
-    int nbFaces   = myMesh->NbFaces();
-    int nbVolumes = myMesh->NbVolumes();
-    if (myDoGroupOfNodes && nbNodes)
-      myNodesDefaultFamilyId = REST_NODES_FAMILY;
-    if (myDoGroupOfEdges && nbEdges)
-      myEdgesDefaultFamilyId = REST_EDGES_FAMILY;
-    if (myDoGroupOfFaces && nbFaces)
-      myFacesDefaultFamilyId = REST_FACES_FAMILY;
-    if (myDoGroupOfVolumes && nbVolumes)
-      myVolumesDefaultFamilyId = REST_VOLUMES_FAMILY;
-
-    MESSAGE("Perform - aFamilyInfo");
-    map<const SMDS_MeshElement *, int> anElemFamMap;
+    // Storing SMDS groups and sub-meshes as med families
+    //----------------------------------------------------
+    int myNodesDefaultFamilyId      = 0;
+    int my0DElementsDefaultFamilyId = 0;
+    int myBallsDefaultFamilyId      = 0;
+    int myEdgesDefaultFamilyId      = 0;
+    int myFacesDefaultFamilyId      = 0;
+    int myVolumesDefaultFamilyId    = 0;
+    int nbNodes      = myMesh->NbNodes();
+    int nb0DElements = myMesh->Nb0DElements();
+    int nbBalls      = myMesh->NbBalls();
+    int nbEdges      = myMesh->NbEdges();
+    int nbFaces      = myMesh->NbFaces();
+    int nbVolumes    = myMesh->NbVolumes();
+    if (myDoGroupOfNodes && nbNodes) myNodesDefaultFamilyId = REST_NODES_FAMILY;
+    if (myDoGroupOfEdges && nbEdges) myEdgesDefaultFamilyId = REST_EDGES_FAMILY;
+    if (myDoGroupOfFaces && nbFaces) myFacesDefaultFamilyId = REST_FACES_FAMILY;
+    if (myDoGroupOfVolumes && nbVolumes) myVolumesDefaultFamilyId = REST_VOLUMES_FAMILY;
+    if (myDoGroupOf0DElems && nb0DElements) my0DElementsDefaultFamilyId = REST_0DELEM_FAMILY;
+    if (myDoGroupOfBalls && nbBalls) myBallsDefaultFamilyId = REST_BALL_FAMILY;
+
+    //MESSAGE("Perform - aFamilyInfo");
     list<DriverMED_FamilyPtr> aFamilies;
     if (myAllSubMeshes) {
       aFamilies = DriverMED_Family::MakeFamilies
@@ -350,29 +464,25 @@ Driver_Mesh::Status DriverMED_W_SMESHDS_Mesh::Perform()
          myDoGroupOfNodes   && nbNodes,
          myDoGroupOfEdges   && nbEdges,
          myDoGroupOfFaces   && nbFaces,
-         myDoGroupOfVolumes && nbVolumes);
-    } else {
+         myDoGroupOfVolumes && nbVolumes,
+         myDoGroupOf0DElems && nb0DElements,
+         myDoGroupOfBalls   && nbBalls);
+    }
+    else {
       aFamilies = DriverMED_Family::MakeFamilies
-        (mySubMeshes, myGroups,
+        (getIterator( mySubMeshes ), myGroups,
          myDoGroupOfNodes   && nbNodes,
          myDoGroupOfEdges   && nbEdges,
          myDoGroupOfFaces   && nbFaces,
-         myDoGroupOfVolumes && nbVolumes);
+         myDoGroupOfVolumes && nbVolumes,
+         myDoGroupOf0DElems && nb0DElements,
+         myDoGroupOfBalls   && nbBalls);
     }
-    list<DriverMED_FamilyPtr>::iterator aFamsIter = aFamilies.begin();
-
-    for (; aFamsIter != aFamilies.end(); aFamsIter++)
+    list<DriverMED_FamilyPtr>::iterator aFamsIter;
+    for (aFamsIter = aFamilies.begin(); aFamsIter != aFamilies.end(); aFamsIter++)
     {
       PFamilyInfo aFamilyInfo = (*aFamsIter)->GetFamilyInfo(myMed,aMeshInfo);
       myMed->SetFamilyInfo(aFamilyInfo);
-      int aFamId = (*aFamsIter)->GetId();
-
-      const set<const SMDS_MeshElement *>& anElems = (*aFamsIter)->GetElements();
-      set<const SMDS_MeshElement *>::const_iterator anElemsIter = anElems.begin();
-      for (; anElemsIter != anElems.end(); anElemsIter++)
-      {
-        anElemFamMap[*anElemsIter] = aFamId;
-      }
     }
 
     // Storing SMDS nodes to the MED file for the MED mesh
@@ -381,655 +491,482 @@ Driver_Mesh::Status DriverMED_W_SMESHDS_Mesh::Perform()
     typedef map<TInt,TInt> TNodeIdMap;
     TNodeIdMap aNodeIdMap;
 #endif
-    TInt aNbElems = myMesh->NbNodes();
-    MED::TIntVector anElemNums(aNbElems);
-    MED::TIntVector aFamilyNums(aNbElems);
-    MED::TFloatVector aCoordinates(aNbElems*aMeshDimension);
-    for(TInt iNode = 0, aStartId = 0; aCoordHelperPtr->Next(); iNode++, aStartId += aMeshDimension){
-      for(TInt iCoord = 0; iCoord < aMeshDimension; iCoord++){
-       aCoordinates[aStartId+iCoord] = aCoordHelperPtr->GetCoord(iCoord);
+    const EModeSwitch   theMode        = eFULL_INTERLACE;
+    const ERepere       theSystem      = eCART;
+    const EBooleen      theIsElemNum   = eVRAI;
+    const EBooleen      theIsElemNames = eFAUX;
+    const EConnectivite theConnMode    = eNOD;
+
+    TInt aNbNodes = myMesh->NbNodes();
+    PNodeInfo aNodeInfo = myMed->CrNodeInfo(aMeshInfo, aNbNodes,
+                                            theMode, theSystem, theIsElemNum, theIsElemNames);
+
+    // find family numbers for nodes
+    TElemFamilyMap anElemFamMap;
+    fillElemFamilyMap( anElemFamMap, aFamilies, SMDSAbs_Node );
+
+    for (TInt iNode = 0; aCoordHelperPtr->Next(); iNode++)
+    {
+      // coordinates
+      TCoordSlice aTCoordSlice = aNodeInfo->GetCoordSlice( iNode );
+      for(TInt iCoord = 0; iCoord < aSpaceDimension; iCoord++){
+        aTCoordSlice[iCoord] = aCoordHelperPtr->GetCoord(iCoord);
       }
+      // node number
       int aNodeID = aCoordHelperPtr->GetID();
-      anElemNums[iNode] = aNodeID;
+      aNodeInfo->SetElemNum( iNode, aNodeID );
 #ifdef _EDF_NODE_IDS_
-      aNodeIdMap[aNodeID] = iNode+1;
+      aNodeIdMap.insert( aNodeIdMap.end(), make_pair( aNodeID, iNode+1 ));
 #endif
+      // family number
       const SMDS_MeshNode* aNode = aCoordHelperPtr->GetNode();
-      if (anElemFamMap.find(aNode) != anElemFamMap.end())
-       aFamilyNums[iNode] = anElemFamMap[aNode];
-      else
-       aFamilyNums[iNode] = myNodesDefaultFamilyId;
+      int famNum = getFamilyId( anElemFamMap, aNode, myNodesDefaultFamilyId );
+      aNodeInfo->SetFamNum( iNode, famNum );
     }
+    anElemFamMap.Clear();
 
-    MED::TStringVector aCoordNames(aMeshDimension);
-    MED::TStringVector aCoordUnits(aMeshDimension);
-    for(TInt iCoord = 0; iCoord < aMeshDimension; iCoord++){
-      aCoordNames[iCoord] = aCoordHelperPtr->GetName(iCoord);
-      aCoordUnits[iCoord] = aCoordHelperPtr->GetUnit(iCoord);
+    // coordinate names and units
+    for (TInt iCoord = 0; iCoord < aSpaceDimension; iCoord++) {
+      aNodeInfo->SetCoordName( iCoord, aCoordHelperPtr->GetName(iCoord));
+      aNodeInfo->SetCoordUnit( iCoord, aCoordHelperPtr->GetUnit(iCoord));
     }
 
-    const ERepere SMDS_COORDINATE_SYSTEM = eCART;
-
-    PNodeInfo aNodeInfo = myMed->CrNodeInfo(aMeshInfo,
-                                           aCoordinates,
-                                           eFULL_INTERLACE,
-                                           SMDS_COORDINATE_SYSTEM,
-                                           aCoordNames,
-                                           aCoordUnits,
-                                           aFamilyNums,
-                                           anElemNums);
-    MESSAGE("Perform - aNodeInfo->GetNbElem() = "<<aNbElems);
+    //MESSAGE("Perform - aNodeInfo->GetNbElem() = "<<aNbNodes);
     myMed->SetNodeInfo(aNodeInfo);
+    aNodeInfo.reset(); // free memory used for arrays
+
+
+    // Storing SMDS elements to the MED file for the MED mesh
+    //-------------------------------------------------------
+    // Write one element type at once in order to minimize memory usage (PAL19276)
 
+    const SMDS_MeshInfo& nbElemInfo = myMesh->GetMeshInfo();
 
-    // Storing others SMDS elements to the MED file for the MED mesh
-    //--------------------------------------------------------------
-    EEntiteMaillage SMDS_MED_ENTITY = eMAILLE;
-    const EConnectivite SMDS_MED_CONNECTIVITY = eNOD;
+    // poly elements are not supported by med-2.1
+    bool polyTypesSupported = ( myMed->CrPolygoneInfo(aMeshInfo,eMAILLE,ePOLYGONE,0,0).get() != 0 );
+    TInt nbPolygonNodes = 0, nbPolyhedronNodes = 0, nbPolyhedronFaces = 0;
 
-    // Storing SMDS Edges
-    if(TInt aNbElems = myMesh->NbEdges()){
+    // nodes on VERTEXes where 0D elements are absent
+    std::vector<const SMDS_MeshElement*> nodesOf0D;
+    std::vector< SMDS_ElemIteratorPtr > iterVec;
+    SMDS_ElemIteratorPtr iterVecIter;
+    if ( myAddODOnVertices && getNodesOfMissing0DOnVert( myMesh, nodesOf0D ))
+    {
+      iterVec.resize(2);
+      iterVec[0] = myMesh->elementsIterator( SMDSAbs_0DElement );
+      iterVec[1] = SMDS_ElemIteratorPtr
+        ( new SMDS_ElementVectorIterator( nodesOf0D.begin(), nodesOf0D.end() ));
+
+      typedef SMDS_IteratorOnIterators
+        < const SMDS_MeshElement *, std::vector< SMDS_ElemIteratorPtr > > TItIterator;
+      iterVecIter = SMDS_ElemIteratorPtr( new TItIterator( iterVec ));
+    }
+
+    // collect info on all geom types
+
+    list< TElemTypeData > aTElemTypeDatas;
+
+    EEntiteMaillage anEntity = eMAILLE;
 #ifdef _ELEMENTS_BY_DIM_
-      SMDS_MED_ENTITY = eARETE;
+    anEntity = eNOEUD_ELEMENT;
 #endif
-      // count edges of diff types
-      int aNbSeg3 = 0, aNbSeg2 = 0;
-      SMDS_EdgeIteratorPtr anIter = myMesh->edgesIterator();
-      while ( anIter->more() )
-        if ( anIter->next()->NbNodes() == 3 )
-          ++aNbSeg3;
-      aNbSeg2 = aNbElems - aNbSeg3;
-
-      TInt aNbSeg2Conn = MED::GetNbNodes(eSEG2);
-      MED::TIntVector aSeg2ElemNums, aSeg2FamilyNums, aSeg2Conn;
-      aSeg2ElemNums  .reserve( aNbSeg2 );
-      aSeg2FamilyNums.reserve( aNbSeg2 );
-      aSeg2Conn      .reserve( aNbSeg2*aNbSeg2Conn );
-
-      TInt aNbSeg3Conn = MED::GetNbNodes(eSEG3);
-      MED::TIntVector aSeg3ElemNums, aSeg3FamilyNums, aSeg3Conn;
-      aSeg3ElemNums  .reserve( aNbSeg3 );
-      aSeg3FamilyNums.reserve( aNbSeg3 );
-      aSeg3Conn      .reserve( aNbSeg3*aNbSeg3Conn );
-
-      anIter = myMesh->edgesIterator();
-      while ( anIter->more() ) {
-       const SMDS_MeshEdge* anElem = anIter->next();
-       TInt aNbNodes = anElem->NbNodes();
-
-       TInt aNbConnectivity;
-       MED::TIntVector* anElemNums;
-        MED::TIntVector* aFamilyNums;
-       MED::TIntVector* aConnectivity;
-        switch(aNbNodes){
-        case 2:
-          aNbConnectivity = aNbSeg2Conn;
-          anElemNums      = &aSeg2ElemNums;
-          aFamilyNums     = &aSeg2FamilyNums;
-          aConnectivity   = &aSeg2Conn;
-          break;
-        case 3:
-          aNbConnectivity = aNbSeg3Conn;
-          anElemNums      = &aSeg3ElemNums;
-          aFamilyNums     = &aSeg3FamilyNums;
-          aConnectivity   = &aSeg3Conn;
-          break;
-        default:
-          break;
-        }
-
-        for(TInt iNode = 0; iNode < aNbNodes; iNode++) {
-         const SMDS_MeshElement* aNode = anElem->GetNode( iNode );
-#ifdef _EDF_NODE_IDS_
-         aConnectivity->push_back( aNodeIdMap[aNode->GetID()] );
-#else
-         aConnectivity->push_back( aNode->GetID() );
+    aTElemTypeDatas.push_back(TElemTypeData(anEntity,
+                                            ePOINT1,
+                                            nbElemInfo.Nb0DElements() + nodesOf0D.size(),
+                                            SMDSAbs_0DElement));
+#ifdef _ELEMENTS_BY_DIM_
+    anEntity = eSTRUCT_ELEMENT;
 #endif
-        }
+    aTElemTypeDatas.push_back( TElemTypeData(anEntity,
+                                             eBALL,
+                                             nbElemInfo.NbBalls(),
+                                             SMDSAbs_Ball));
+#ifdef _ELEMENTS_BY_DIM_
+    anEntity = eARETE;
+#endif
+    aTElemTypeDatas.push_back( TElemTypeData(anEntity,
+                                             eSEG2,
+                                             nbElemInfo.NbEdges( ORDER_LINEAR ),
+                                             SMDSAbs_Edge));
+    aTElemTypeDatas.push_back( TElemTypeData(anEntity,
+                                             eSEG3,
+                                             nbElemInfo.NbEdges( ORDER_QUADRATIC ),
+                                             SMDSAbs_Edge));
+#ifdef _ELEMENTS_BY_DIM_
+    anEntity = eFACE;
+#endif
+    aTElemTypeDatas.push_back( TElemTypeData(anEntity,
+                                             eTRIA3,
+                                             nbElemInfo.NbTriangles( ORDER_LINEAR ),
+                                             SMDSAbs_Face));
+    aTElemTypeDatas.push_back( TElemTypeData(anEntity,
+                                             eTRIA6,
+                                             nbElemInfo.NbTriangles( ORDER_QUADRATIC ) -
+                                             nbElemInfo.NbBiQuadTriangles(),
+                                             SMDSAbs_Face));
+    aTElemTypeDatas.push_back( TElemTypeData(anEntity,
+                                             eTRIA7,
+                                             nbElemInfo.NbBiQuadTriangles(),
+                                             SMDSAbs_Face));
+    aTElemTypeDatas.push_back( TElemTypeData(anEntity,
+                                             eQUAD4,
+                                             nbElemInfo.NbQuadrangles( ORDER_LINEAR ),
+                                             SMDSAbs_Face));
+    aTElemTypeDatas.push_back( TElemTypeData(anEntity,
+                                             eQUAD8,
+                                             nbElemInfo.NbQuadrangles( ORDER_QUADRATIC ) -
+                                             nbElemInfo.NbBiQuadQuadrangles(),
+                                             SMDSAbs_Face));
+    aTElemTypeDatas.push_back( TElemTypeData(anEntity,
+                                             eQUAD9,
+                                             nbElemInfo.NbBiQuadQuadrangles(),
+                                             SMDSAbs_Face));
+    if ( polyTypesSupported ) {
+      aTElemTypeDatas.push_back( TElemTypeData(anEntity,
+                                               ePOLYGONE,
+                                               nbElemInfo.NbPolygons( ORDER_LINEAR ),
+                                               SMDSAbs_Face));
+      // we need one more loop on poly elements to count nb of their nodes
+      aTElemTypeDatas.push_back( TElemTypeData(anEntity,
+                                               ePOLYGONE,
+                                               nbElemInfo.NbPolygons( ORDER_LINEAR ),
+                                               SMDSAbs_Face));
+      aTElemTypeDatas.push_back( TElemTypeData(anEntity,
+                                               ePOLYGON2,
+                                               nbElemInfo.NbPolygons( ORDER_QUADRATIC ),
+                                               SMDSAbs_Face));
+      // we need one more loop on QUAD poly elements to count nb of their nodes
+      aTElemTypeDatas.push_back( TElemTypeData(anEntity,
+                                               ePOLYGON2,
+                                               nbElemInfo.NbPolygons( ORDER_QUADRATIC ),
+                                               SMDSAbs_Face));
+    }
+#ifdef _ELEMENTS_BY_DIM_
+    anEntity = eMAILLE;
+#endif
+    aTElemTypeDatas.push_back( TElemTypeData(anEntity,
+                                             eTETRA4,
+                                             nbElemInfo.NbTetras( ORDER_LINEAR ),
+                                             SMDSAbs_Volume));
+    aTElemTypeDatas.push_back( TElemTypeData(anEntity,
+                                             eTETRA10,
+                                             nbElemInfo.NbTetras( ORDER_QUADRATIC ),
+                                             SMDSAbs_Volume));
+    aTElemTypeDatas.push_back( TElemTypeData(anEntity,
+                                             ePYRA5,
+                                             nbElemInfo.NbPyramids( ORDER_LINEAR ),
+                                             SMDSAbs_Volume));
+    aTElemTypeDatas.push_back( TElemTypeData(anEntity,
+                                             ePYRA13,
+                                             nbElemInfo.NbPyramids( ORDER_QUADRATIC ),
+                                             SMDSAbs_Volume));
+    aTElemTypeDatas.push_back( TElemTypeData(anEntity,
+                                             ePENTA6,
+                                             nbElemInfo.NbPrisms( ORDER_LINEAR ),
+                                             SMDSAbs_Volume));
+    aTElemTypeDatas.push_back( TElemTypeData(anEntity,
+                                             ePENTA15,
+                                             nbElemInfo.NbPrisms( ORDER_QUADRATIC ),
+                                             SMDSAbs_Volume));
+    aTElemTypeDatas.push_back( TElemTypeData(anEntity,
+                                             eHEXA8,
+                                             nbElemInfo.NbHexas( ORDER_LINEAR ),
+                                             SMDSAbs_Volume));
+    aTElemTypeDatas.push_back( TElemTypeData(anEntity,
+                                             eHEXA20,
+                                             nbElemInfo.NbHexas( ORDER_QUADRATIC )-
+                                             nbElemInfo.NbTriQuadHexas(),
+                                             SMDSAbs_Volume));
+    aTElemTypeDatas.push_back( TElemTypeData(anEntity,
+                                             eHEXA27,
+                                             nbElemInfo.NbTriQuadHexas(),
+                                             SMDSAbs_Volume));
+    aTElemTypeDatas.push_back( TElemTypeData(anEntity,
+                                             eOCTA12,
+                                             nbElemInfo.NbHexPrisms(),
+                                             SMDSAbs_Volume));
+    if ( polyTypesSupported ) {
+      aTElemTypeDatas.push_back( TElemTypeData(anEntity,
+                                               ePOLYEDRE,
+                                               nbElemInfo.NbPolyhedrons(),
+                                               SMDSAbs_Volume));
+      // we need one more loop on poly elements to count nb of their nodes
+      aTElemTypeDatas.push_back( TElemTypeData(anEntity,
+                                               ePOLYEDRE,
+                                               nbElemInfo.NbPolyhedrons(),
+                                               SMDSAbs_Volume));
+    }
 
-       anElemNums->push_back(anElem->GetID());
+    vector< bool > isElemFamMapBuilt( SMDSAbs_NbElementTypes, false );
 
-        map<const SMDS_MeshElement*,int>::iterator edge_fam = anElemFamMap.find( anElem );
-        if ( edge_fam != anElemFamMap.end() )
-          aFamilyNums->push_back( edge_fam->second );
-        else
-          aFamilyNums->push_back( myEdgesDefaultFamilyId );
-      }
-      
-      if ( aNbSeg2 ) {
-        PCellInfo aCellInfo = myMed->CrCellInfo(aMeshInfo,
-                                                SMDS_MED_ENTITY,
-                                                eSEG2,
-                                                aSeg2Conn,
-                                                SMDS_MED_CONNECTIVITY,
-                                                aSeg2FamilyNums,
-                                                aSeg2ElemNums);
-        myMed->SetCellInfo(aCellInfo);
-      }
-      if ( aNbSeg3 ) {
-        PCellInfo aCellInfo = myMed->CrCellInfo(aMeshInfo,
-                                                SMDS_MED_ENTITY,
-                                                eSEG3,
-                                                aSeg3Conn,
-                                                SMDS_MED_CONNECTIVITY,
-                                                aSeg3FamilyNums,
-                                                aSeg3ElemNums);
-        myMed->SetCellInfo(aCellInfo);
+    // loop on all geom types of elements
+
+    list< TElemTypeData >::iterator aElemTypeData = aTElemTypeDatas.begin();
+    for ( ; aElemTypeData != aTElemTypeDatas.end(); ++aElemTypeData )
+    {
+      if ( aElemTypeData->_nbElems == 0 )
+        continue;
+
+      int defaultFamilyId = 0;
+      switch ( aElemTypeData->_smdsType ) {
+      case SMDSAbs_0DElement: defaultFamilyId = my0DElementsDefaultFamilyId; break;
+      case SMDSAbs_Ball:      defaultFamilyId = myBallsDefaultFamilyId;      break;
+      case SMDSAbs_Edge:      defaultFamilyId = myEdgesDefaultFamilyId;      break;
+      case SMDSAbs_Face:      defaultFamilyId = myFacesDefaultFamilyId;      break;
+      case SMDSAbs_Volume:    defaultFamilyId = myVolumesDefaultFamilyId;    break;
+      default:
+        continue;
       }
-    }
 
-    // Storing SMDS Faces
-    if(TInt aNbElems = myMesh->NbFaces()){
-      SMDS_FaceIteratorPtr anIter = myMesh->facesIterator();
-#ifdef _ELEMENTS_BY_DIM_
-      SMDS_MED_ENTITY = eFACE;
-#endif
-      TInt aNbTriaConn = MED::GetNbNodes(eTRIA3);
-      MED::TIntVector anTriaElemNums; 
-      anTriaElemNums.reserve(aNbElems);
-      MED::TIntVector aTriaFamilyNums;
-      aTriaFamilyNums.reserve(aNbElems);
-      MED::TIntVector aTriaConn;
-      aTriaConn.reserve(aNbElems*aNbTriaConn);
-
-      TInt aNbTria6Conn = MED::GetNbNodes(eTRIA6);
-      MED::TIntVector anTria6ElemNums; 
-      anTria6ElemNums.reserve(aNbElems);
-      MED::TIntVector aTria6FamilyNums;
-      aTria6FamilyNums.reserve(aNbElems);
-      MED::TIntVector aTria6Conn;
-      aTria6Conn.reserve(aNbElems*aNbTria6Conn);
-
-      TInt aNbQuadConn = MED::GetNbNodes(eQUAD4);
-      MED::TIntVector aQuadElemNums;
-      aQuadElemNums.reserve(aNbElems);
-      MED::TIntVector aQuadFamilyNums;
-      aQuadFamilyNums.reserve(aNbElems);
-      MED::TIntVector aQuadConn;
-      aQuadConn.reserve(aNbElems*aNbQuadConn);
-
-      TInt aNbQuad8Conn = MED::GetNbNodes(eQUAD8);
-      MED::TIntVector aQuad8ElemNums;
-      aQuad8ElemNums.reserve(aNbElems);
-      MED::TIntVector aQuad8FamilyNums;
-      aQuad8FamilyNums.reserve(aNbElems);
-      MED::TIntVector aQuad8Conn;
-      aQuad8Conn.reserve(aNbElems*aNbQuad8Conn);
-
-      MED::TIntVector aPolygoneElemNums;
-      aPolygoneElemNums.reserve(aNbElems);
-      MED::TIntVector aPolygoneInds;
-      aPolygoneInds.reserve(aNbElems + 1);
-      aPolygoneInds.push_back(1); // reference on the first element in the connectivities
-      MED::TIntVector aPolygoneFamilyNums;
-      aPolygoneFamilyNums.reserve(aNbElems);
-      MED::TIntVector aPolygoneConn;
-      aPolygoneConn.reserve(aNbElems*aNbQuadConn);
-
-      for(TInt iElem = 0; iElem < aNbElems && anIter->more(); iElem++){
-       const SMDS_MeshFace* anElem = anIter->next();
-       TInt aNbNodes = anElem->NbNodes();
-       SMDS_ElemIteratorPtr aNodesIter = anElem->nodesIterator();
-       TInt aNbConnectivity;
-       MED::TIntVector* anElemNums;
-        MED::TIntVector* aFamilyNums;
-       MED::TIntVector* aConnectivity;
-        if (anElem->IsPoly()) {
-         aNbConnectivity = aNbNodes;
-          anElemNums = &aPolygoneElemNums;
-          aFamilyNums = &aPolygoneFamilyNums;
-          aConnectivity = &aPolygoneConn;
-        }
-        else {
-          switch(aNbNodes){
-          case 3:
-            aNbConnectivity = aNbTriaConn;
-            anElemNums = &anTriaElemNums;
-            aFamilyNums = &aTriaFamilyNums;
-            aConnectivity = &aTriaConn;
-            break;
-          case 4:
-            aNbConnectivity = aNbQuadConn;
-            anElemNums = &aQuadElemNums;
-            aFamilyNums = &aQuadFamilyNums;
-            aConnectivity = &aQuadConn;
-            break;
-          case 6:
-            aNbConnectivity = aNbTria6Conn;
-            anElemNums = &anTria6ElemNums;
-            aFamilyNums = &aTria6FamilyNums;
-            aConnectivity = &aTria6Conn;
-            break;
-          case 8:
-            aNbConnectivity = aNbQuad8Conn;
-            anElemNums = &aQuad8ElemNums;
-            aFamilyNums = &aQuad8FamilyNums;
-            aConnectivity = &aQuad8Conn;
-            break;
-          default:
-            break;
+      // iterator on elements of a current type
+      SMDS_ElemIteratorPtr elemIterator;
+      int iElem = 0;
+
+      // Treat POLYGONs
+      // ---------------
+      if ( aElemTypeData->_geomType == ePOLYGONE ||
+           aElemTypeData->_geomType == ePOLYGON2 )
+      {
+        if ( aElemTypeData->_geomType == ePOLYGONE )
+          elemIterator = myMesh->elementEntityIterator( SMDSEntity_Polygon );
+        else
+          elemIterator = myMesh->elementEntityIterator( SMDSEntity_Quad_Polygon );
+
+        if ( nbPolygonNodes == 0 ) {
+          // Count nb of nodes
+          while ( elemIterator->more() ) {
+            const SMDS_MeshElement* anElem = elemIterator->next();
+            nbPolygonNodes += anElem->NbNodes();
+            if ( ++iElem == aElemTypeData->_nbElems )
+              break;
           }
         }
-       MED::TIntVector aVector(aNbNodes);
-       for(TInt iNode = 0; aNodesIter->more(); iNode++){
-         const SMDS_MeshElement* aNode = aNodesIter->next();
+        else {
+          // Store in med file
+          PPolygoneInfo aPolygoneInfo = myMed->CrPolygoneInfo(aMeshInfo,
+                                                              aElemTypeData->_entity,
+                                                              aElemTypeData->_geomType,
+                                                              aElemTypeData->_nbElems,
+                                                              nbPolygonNodes,
+                                                              theConnMode, theIsElemNum,
+                                                              theIsElemNames);
+          TElemNum & index = *(aPolygoneInfo->myIndex.get());
+          index[0] = 1;
+
+          while ( elemIterator->more() )
+          {
+            const SMDS_MeshElement* anElem = elemIterator->next();
+            // index
+            TInt aNbNodes = anElem->NbNodes();
+            index[ iElem+1 ] = index[ iElem ] + aNbNodes;
+
+            // connectivity
+            TConnSlice aTConnSlice = aPolygoneInfo->GetConnSlice( iElem );
+            for(TInt iNode = 0; iNode < aNbNodes; iNode++) {
+              const SMDS_MeshElement* aNode = anElem->GetNode( iNode );
 #ifdef _EDF_NODE_IDS_
-         aVector[iNode] = aNodeIdMap[aNode->GetID()];
+              aTConnSlice[ iNode ] = aNodeIdMap[aNode->GetID()];
 #else
-         aVector[iNode] = aNode->GetID();
+              aTConnSlice[ iNode ] = aNode->GetID();
 #endif
-       }
-
-       TInt aSize = aConnectivity->size();
-       aConnectivity->resize(aSize+aNbConnectivity);
-       // There is some differences between SMDS and MED in cells mapping
-       switch(aNbNodes){
-       case 4:
-         (*aConnectivity)[aSize+0] = aVector[0];
-         (*aConnectivity)[aSize+1] = aVector[1];
-         (*aConnectivity)[aSize+2] = aVector[3];  
-         (*aConnectivity)[aSize+3] = aVector[2];  
-       default:
-         for(TInt iNode = 0; iNode < aNbNodes; iNode++) 
-           (*aConnectivity)[aSize+iNode] = aVector[iNode];
-       }
-
-        if (anElem->IsPoly()) {
-          // fill indices for polygonal element
-          TInt aPrevPos = aPolygoneInds.back();
-          aPolygoneInds.push_back(aPrevPos + aNbNodes);
-        }
+            }
+            // element number
+            aPolygoneInfo->SetElemNum( iElem, anElem->GetID() );
 
-       anElemNums->push_back(anElem->GetID());
+            // family number
+            int famNum = getFamilyId( anElemFamMap, anElem, defaultFamilyId );
+            aPolygoneInfo->SetFamNum( iElem, famNum );
 
-        if (anElemFamMap.find(anElem) != anElemFamMap.end())
-          aFamilyNums->push_back(anElemFamMap[anElem]);
-        else
-          aFamilyNums->push_back(myFacesDefaultFamilyId);
-      }
-      if(TInt aNbElems = anTriaElemNums.size()){
-       PCellInfo aCellInfo = myMed->CrCellInfo(aMeshInfo,
-                                               SMDS_MED_ENTITY,
-                                               eTRIA3,
-                                               aTriaConn,
-                                               SMDS_MED_CONNECTIVITY,
-                                               aTriaFamilyNums,
-                                               anTriaElemNums);
-       MESSAGE("Perform - anEntity = "<<SMDS_MED_ENTITY<<"; aGeom = "<<eTRIA3<<"; aNbElems = "<<aNbElems);
-       myMed->SetCellInfo(aCellInfo);
-      }
-      if(TInt aNbElems = aQuadElemNums.size()){
-       PCellInfo aCellInfo = myMed->CrCellInfo(aMeshInfo,
-                                               SMDS_MED_ENTITY,
-                                               eQUAD4,
-                                               aQuadConn,
-                                               SMDS_MED_CONNECTIVITY,
-                                               aQuadFamilyNums,
-                                               aQuadElemNums);
-       MESSAGE("Perform - anEntity = "<<SMDS_MED_ENTITY<<"; aGeom = "<<eQUAD4<<"; aNbElems = "<<aNbElems);
-       myMed->SetCellInfo(aCellInfo);
-      }
-      if(TInt aNbElems = anTria6ElemNums.size()){
-       PCellInfo aCellInfo = myMed->CrCellInfo(aMeshInfo,
-                                               SMDS_MED_ENTITY,
-                                               eTRIA6,
-                                               aTria6Conn,
-                                               SMDS_MED_CONNECTIVITY,
-                                               aTria6FamilyNums,
-                                               anTria6ElemNums);
-       MESSAGE("Perform - anEntity = "<<SMDS_MED_ENTITY<<"; aGeom = "<<eTRIA6<<"; aNbElems = "<<aNbElems);
-       myMed->SetCellInfo(aCellInfo);
-      }
-      if(TInt aNbElems = aQuad8ElemNums.size()){
-       PCellInfo aCellInfo = myMed->CrCellInfo(aMeshInfo,
-                                               SMDS_MED_ENTITY,
-                                               eQUAD8,
-                                               aQuad8Conn,
-                                               SMDS_MED_CONNECTIVITY,
-                                               aQuad8FamilyNums,
-                                               aQuad8ElemNums);
-       MESSAGE("Perform - anEntity = "<<SMDS_MED_ENTITY<<"; aGeom = "<<eQUAD8<<"; aNbElems = "<<aNbElems);
-       myMed->SetCellInfo(aCellInfo);
-      }
-      if(TInt aNbElems = aPolygoneElemNums.size()){
-        // add one element in connectivities,
-        // referenced by the last element in indices
-        aPolygoneConn.push_back(0);
-
-       PPolygoneInfo aCellInfo = myMed->CrPolygoneInfo(aMeshInfo,
-                                                        SMDS_MED_ENTITY,
-                                                        ePOLYGONE,
-                                                        aPolygoneInds,
-                                                        aPolygoneConn,
-                                                        SMDS_MED_CONNECTIVITY,
-                                                        aPolygoneFamilyNums,
-                                                        aPolygoneElemNums);
-       MESSAGE("Perform - anEntity = "<<SMDS_MED_ENTITY<<"; aGeom = "<<ePOLYGONE<<"; aNbElems = "<<aNbElems);
-       myMed->SetPolygoneInfo(aCellInfo);
+            if ( ++iElem == aPolygoneInfo->GetNbElem() )
+              break;
+          }
+          myMed->SetPolygoneInfo(aPolygoneInfo);
+
+          nbPolygonNodes = 0; // to treat next polygon type
+        }
       }
-    }
 
-    // Storing SMDS Volumes
-    if(TInt aNbElems = myMesh->NbVolumes()){
-      SMDS_VolumeIteratorPtr anIter = myMesh->volumesIterator();
-#ifdef _ELEMENTS_BY_DIM_
-      SMDS_MED_ENTITY = eMAILLE;
+      // Treat POLYEDREs
+      // ----------------
+      else if (aElemTypeData->_geomType == ePOLYEDRE )
+      {
+        elemIterator = myMesh->elementGeomIterator( SMDSGeom_POLYHEDRA );
+        
+        if ( nbPolyhedronNodes == 0 ) {
+          // Count nb of nodes
+          while ( elemIterator->more() ) {
+            const SMDS_MeshElement*  anElem = elemIterator->next();
+            const SMDS_VtkVolume *aPolyedre = dynamic_cast<const SMDS_VtkVolume*>(anElem);
+            if ( !aPolyedre ) continue;
+            nbPolyhedronNodes += aPolyedre->NbNodes();
+            nbPolyhedronFaces += aPolyedre->NbFaces();
+            if ( ++iElem == aElemTypeData->_nbElems )
+              break;
+          }
+        }
+        else {
+          // Store in med file
+          PPolyedreInfo aPolyhInfo = myMed->CrPolyedreInfo(aMeshInfo,
+                                                           aElemTypeData->_entity,
+                                                           aElemTypeData->_geomType,
+                                                           aElemTypeData->_nbElems,
+                                                           nbPolyhedronFaces+1,
+                                                           nbPolyhedronNodes,
+                                                           theConnMode,
+                                                           theIsElemNum,
+                                                           theIsElemNames);
+          TElemNum & index = *(aPolyhInfo->myIndex.get());
+          TElemNum & faces = *(aPolyhInfo->myFaces.get());
+          TElemNum & conn  = *(aPolyhInfo->myConn.get());
+          index[0] = 1;
+          faces[0] = 1;
+
+          TInt iFace = 0, iNode = 0;
+          while ( elemIterator->more() )
+          {
+            const SMDS_MeshElement*  anElem = elemIterator->next();
+            const SMDS_VtkVolume *aPolyedre = dynamic_cast<const SMDS_VtkVolume*>(anElem);
+            if ( !aPolyedre ) continue;
+            // index
+            TInt aNbFaces = aPolyedre->NbFaces();
+            index[ iElem+1 ] = index[ iElem ] + aNbFaces;
+
+            // face index
+            for (TInt f = 1; f <= aNbFaces; ++f, ++iFace ) {
+              int aNbFaceNodes = aPolyedre->NbFaceNodes( f );
+              faces[ iFace+1 ] = faces[ iFace ] + aNbFaceNodes;
+            }
+            // connectivity
+            SMDS_ElemIteratorPtr nodeIt = anElem->nodesIterator();
+            while ( nodeIt->more() ) {
+              const SMDS_MeshElement* aNode = nodeIt->next();
+#ifdef _EDF_NODE_IDS_
+              conn[ iNode ] = aNodeIdMap[aNode->GetID()];
+#else
+              conn[ iNode ] = aNode->GetID();
 #endif
-      TInt aNbTetraConn = MED::GetNbNodes(eTETRA4);
-      MED::TIntVector anTetraElemNums; 
-      anTetraElemNums.reserve(aNbElems);
-      MED::TIntVector aTetraFamilyNums;
-      aTetraFamilyNums.reserve(aNbElems);
-      MED::TIntVector aTetraConn;
-      aTetraConn.reserve(aNbElems*aNbTetraConn);
-
-      TInt aNbPyraConn = MED::GetNbNodes(ePYRA5);
-      MED::TIntVector anPyraElemNums; 
-      anPyraElemNums.reserve(aNbElems);
-      MED::TIntVector aPyraFamilyNums;
-      aPyraFamilyNums.reserve(aNbElems);
-      MED::TIntVector aPyraConn;
-      aPyraConn.reserve(aNbElems*aNbPyraConn);
-
-      TInt aNbPentaConn = MED::GetNbNodes(ePENTA6);
-      MED::TIntVector anPentaElemNums; 
-      anPentaElemNums.reserve(aNbElems);
-      MED::TIntVector aPentaFamilyNums;
-      aPentaFamilyNums.reserve(aNbElems);
-      MED::TIntVector aPentaConn;
-      aPentaConn.reserve(aNbElems*aNbPentaConn);
-
-      TInt aNbHexaConn = MED::GetNbNodes(eHEXA8);
-      MED::TIntVector aHexaElemNums;
-      aHexaElemNums.reserve(aNbElems);
-      MED::TIntVector aHexaFamilyNums;
-      aHexaFamilyNums.reserve(aNbElems);
-      MED::TIntVector aHexaConn;
-      aHexaConn.reserve(aNbElems*aNbHexaConn);
-
-      TInt aNbTetra10Conn = MED::GetNbNodes(eTETRA10);
-      MED::TIntVector anTetra10ElemNums; 
-      anTetra10ElemNums.reserve(aNbElems);
-      MED::TIntVector aTetra10FamilyNums;
-      aTetra10FamilyNums.reserve(aNbElems);
-      MED::TIntVector aTetra10Conn;
-      aTetra10Conn.reserve(aNbElems*aNbTetra10Conn);
-
-      TInt aNbPyra13Conn = MED::GetNbNodes(ePYRA13);
-      MED::TIntVector anPyra13ElemNums; 
-      anPyra13ElemNums.reserve(aNbElems);
-      MED::TIntVector aPyra13FamilyNums;
-      aPyra13FamilyNums.reserve(aNbElems);
-      MED::TIntVector aPyra13Conn;
-      aPyra13Conn.reserve(aNbElems*aNbPyra13Conn);
-
-      TInt aNbPenta15Conn = MED::GetNbNodes(ePENTA15);
-      MED::TIntVector anPenta15ElemNums; 
-      anPenta15ElemNums.reserve(aNbElems);
-      MED::TIntVector aPenta15FamilyNums;
-      aPenta15FamilyNums.reserve(aNbElems);
-      MED::TIntVector aPenta15Conn;
-      aPenta15Conn.reserve(aNbElems*aNbPenta15Conn);
-
-      TInt aNbHexa20Conn = MED::GetNbNodes(eHEXA20);
-      MED::TIntVector aHexa20ElemNums;
-      aHexa20ElemNums.reserve(aNbElems);
-      MED::TIntVector aHexa20FamilyNums;
-      aHexa20FamilyNums.reserve(aNbElems);
-      MED::TIntVector aHexa20Conn;
-      aHexa20Conn.reserve(aNbElems*aNbHexa20Conn);
-
-      MED::TIntVector aPolyedreElemNums;
-      aPolyedreElemNums.reserve(aNbElems);
-      MED::TIntVector aPolyedreInds;
-      aPolyedreInds.reserve(aNbElems + 1);
-      aPolyedreInds.push_back(1); // reference on the first element in the faces
-      MED::TIntVector aPolyedreFaces;
-      aPolyedreFaces.reserve(aNbElems + 1);
-      aPolyedreFaces.push_back(1); // reference on the first element in the connectivities
-      MED::TIntVector aPolyedreFamilyNums;
-      aPolyedreFamilyNums.reserve(aNbElems);
-      MED::TIntVector aPolyedreConn;
-      aPolyedreConn.reserve(aNbElems*aNbHexaConn);
-
-      for(TInt iElem = 0; iElem < aNbElems && anIter->more(); iElem++){
-       const SMDS_MeshVolume* anElem = anIter->next();
-
-        MED::TIntVector* anElemNums;
-        MED::TIntVector* aFamilyNums;
-
-        if (anElem->IsPoly()) {
-          const SMDS_PolyhedralVolumeOfNodes* aPolyedre =
-            (const SMDS_PolyhedralVolumeOfNodes*) anElem;
-          if (!aPolyedre) {
-            MESSAGE("Warning: bad volumic element");
-            continue;
+              ++iNode;
+            }
+            // element number
+            aPolyhInfo->SetElemNum( iElem, anElem->GetID() );
+
+            // family number
+            int famNum = getFamilyId( anElemFamMap, anElem, defaultFamilyId );
+            aPolyhInfo->SetFamNum( iElem, famNum );
+
+            if ( ++iElem == aPolyhInfo->GetNbElem() )
+              break;
           }
+          myMed->SetPolyedreInfo(aPolyhInfo);
+        }
+      } // if (aElemTypeData->_geomType == ePOLYEDRE )
 
-          anElemNums = &aPolyedreElemNums;
-          aFamilyNums = &aPolyedreFamilyNums;
+      // Treat BALLs
+      // ----------------
+      else if (aElemTypeData->_geomType == eBALL )
+      {
+        // allocate data arrays
+        PBallInfo aBallInfo = myMed->CrBallInfo( aMeshInfo, aElemTypeData->_nbElems );
+
+        // build map of family numbers for this type
+        if ( !isElemFamMapBuilt[ aElemTypeData->_smdsType ])
+        {
+          fillElemFamilyMap( anElemFamMap, aFamilies, aElemTypeData->_smdsType );
+          isElemFamMapBuilt[ aElemTypeData->_smdsType ] = true;
+        }
 
-          TInt aNodeId, aNbFaces = aPolyedre->NbFaces();
-          for (int iface = 1; iface <= aNbFaces; iface++) {
-            int aNbFaceNodes = aPolyedre->NbFaceNodes(iface);
-            for (int inode = 1; inode <= aNbFaceNodes; inode++) {
-              aNodeId = aPolyedre->GetFaceNode(iface, inode)->GetID();
+        elemIterator = myMesh->elementsIterator( SMDSAbs_Ball );
+        while ( elemIterator->more() )
+        {
+          const SMDS_MeshElement* anElem = elemIterator->next();
+          // connectivity
+          const SMDS_MeshElement* aNode = anElem->GetNode( 0 );
 #ifdef _EDF_NODE_IDS_
-              aPolyedreConn.push_back(aNodeIdMap[aNodeId]);
+          (*aBallInfo->myConn)[ iElem ] = aNodeIdMap[aNode->GetID()];
 #else
-              aPolyedreConn.push_back(aNodeId);
+          (*aBallInfo->myConn)[ iElem ] = aNode->GetID();
 #endif
-            }
-            TInt aPrevPos = aPolyedreFaces.back();
-            aPolyedreFaces.push_back(aPrevPos + aNbFaceNodes);
-          }
-          TInt aPrevPos = aPolyedreInds.back();
-          aPolyedreInds.push_back(aPrevPos + aNbFaces);
+          // element number
+          aBallInfo->SetElemNum( iElem, anElem->GetID() );
 
+          // diameter
+          aBallInfo->myDiameters[ iElem ] =
+            static_cast<const SMDS_BallElement*>( anElem )->GetDiameter();
+
+          // family number
+          int famNum = getFamilyId( anElemFamMap, anElem, defaultFamilyId );
+          aBallInfo->SetFamNum( iElem, famNum );
+          ++iElem;
         }
-        else {
-          TInt aNbNodes = anElem->NbNodes();
-          SMDS_ElemIteratorPtr aNodesIter = anElem->nodesIterator();
-          TInt aNbConnectivity;
-          MED::TIntVector* aConnectivity;
-          switch(aNbNodes){
-          case 4:
-            aNbConnectivity = aNbTetraConn;
-            anElemNums = &anTetraElemNums;
-            aFamilyNums = &aTetraFamilyNums;
-            aConnectivity = &aTetraConn;
-            break;
-          case 5:
-            aNbConnectivity = aNbPyraConn;
-            anElemNums = &anPyraElemNums;
-            aFamilyNums = &aPyraFamilyNums;
-            aConnectivity = &aPyraConn;
-            break;
-          case 6:
-            aNbConnectivity = aNbPentaConn;
-            anElemNums = &anPentaElemNums;
-            aFamilyNums = &aPentaFamilyNums;
-            aConnectivity = &aPentaConn;
-            break;
-          case 8:
-            aNbConnectivity = aNbHexaConn;
-            anElemNums = &aHexaElemNums;
-            aFamilyNums = &aHexaFamilyNums;
-            aConnectivity = &aHexaConn;
-           break;
-          case 10:
-            aNbConnectivity = aNbTetra10Conn;
-            anElemNums = &anTetra10ElemNums;
-            aFamilyNums = &aTetra10FamilyNums;
-            aConnectivity = &aTetra10Conn;
-            break;
-          case 13:
-            aNbConnectivity = aNbPyra13Conn;
-            anElemNums = &anPyra13ElemNums;
-            aFamilyNums = &aPyra13FamilyNums;
-            aConnectivity = &aPyra13Conn;
-            break;
-          case 15:
-            aNbConnectivity = aNbPenta15Conn;
-            anElemNums = &anPenta15ElemNums;
-            aFamilyNums = &aPenta15FamilyNums;
-            aConnectivity = &aPenta15Conn;
-            break;
-          case 20:
-            aNbConnectivity = aNbHexa20Conn;
-            anElemNums = &aHexa20ElemNums;
-            aFamilyNums = &aHexa20FamilyNums;
-            aConnectivity = &aHexa20Conn;
-          }
+        // store data in a file
+        myMed->SetBallInfo(aBallInfo);
+      }
 
-          TInt aSize = aConnectivity->size();
-          aConnectivity->resize(aSize + aNbConnectivity);
+      else
+      {
+        // Treat standard types
+        // ---------------------
+
+        // allocate data arrays
+        PCellInfo aCellInfo = myMed->CrCellInfo( aMeshInfo,
+                                                 aElemTypeData->_entity,
+                                                 aElemTypeData->_geomType,
+                                                 aElemTypeData->_nbElems,
+                                                 theConnMode,
+                                                 theIsElemNum,
+                                                 theIsElemNames);
+        // build map of family numbers for this type
+        if ( !isElemFamMapBuilt[ aElemTypeData->_smdsType ])
+        {
+          //cout << " fillElemFamilyMap()" << endl;
+          fillElemFamilyMap( anElemFamMap, aFamilies, aElemTypeData->_smdsType );
+          isElemFamMapBuilt[ aElemTypeData->_smdsType ] = true;
+        }
 
-          MED::TIntVector aVector(aNbNodes);
-          for(TInt iNode = 0; aNodesIter->more(); iNode++){
-            const SMDS_MeshElement* aNode = aNodesIter->next();
+        TInt aNbNodes = MED::GetNbNodes(aElemTypeData->_geomType);
+        elemIterator = myMesh->elementsIterator( aElemTypeData->_smdsType );
+        if ( aElemTypeData->_smdsType == SMDSAbs_0DElement && ! nodesOf0D.empty() )
+          elemIterator = iterVecIter;
+        while ( elemIterator->more() )
+        {
+          const SMDS_MeshElement* anElem = elemIterator->next();
+          if ( anElem->NbNodes() != aNbNodes || anElem->IsPoly() )
+            continue; // other geometry
+
+          // connectivity
+          TConnSlice aTConnSlice = aCellInfo->GetConnSlice( iElem );
+          for (TInt iNode = 0; iNode < aNbNodes; iNode++) {
+            const SMDS_MeshElement* aNode = anElem->GetNode( iNode );
 #ifdef _EDF_NODE_IDS_
-            aVector[iNode] = aNodeIdMap[aNode->GetID()];
+            aTConnSlice[ iNode ] = aNodeIdMap[aNode->GetID()];
 #else
-            aVector[iNode] = aNode->GetID();
+            aTConnSlice[ iNode ] = aNode->GetID();
 #endif
           }
-          // There is some difference between SMDS and MED in cells mapping
-          switch(aNbNodes){
-          case 5:
-            (*aConnectivity)[aSize+0] = aVector[0];
-            (*aConnectivity)[aSize+1] = aVector[3];
-            (*aConnectivity)[aSize+2] = aVector[2];  
-            (*aConnectivity)[aSize+3] = aVector[1];  
-            (*aConnectivity)[aSize+4] = aVector[4];  
-          default:
-            for(TInt iNode = 0; iNode < aNbNodes; iNode++) 
-              (*aConnectivity)[aSize+iNode] = aVector[iNode];
-          }
-        }
+          // element number
+          aCellInfo->SetElemNum( iElem, anElem->GetID() );
 
-        anElemNums->push_back(anElem->GetID());
+          // family number
+          int famNum = getFamilyId( anElemFamMap, anElem, defaultFamilyId );
+          aCellInfo->SetFamNum( iElem, famNum );
 
-        if (anElemFamMap.find(anElem) != anElemFamMap.end())
-          aFamilyNums->push_back(anElemFamMap[anElem]);
-        else
-          aFamilyNums->push_back(myVolumesDefaultFamilyId);
+          if ( ++iElem == aCellInfo->GetNbElem() )
+            break;
+        }
+        // store data in a file
+        myMed->SetCellInfo(aCellInfo);
       }
 
-      if(TInt aNbElems = anTetraElemNums.size()){
-       PCellInfo aCellInfo = myMed->CrCellInfo(aMeshInfo,
-                                               SMDS_MED_ENTITY,
-                                               eTETRA4,
-                                               aTetraConn,
-                                               SMDS_MED_CONNECTIVITY,
-                                               aTetraFamilyNums,
-                                               anTetraElemNums);
-       MESSAGE("Perform - anEntity = "<<SMDS_MED_ENTITY<<"; aGeom = "<<eTETRA4<<"; aNbElems = "<<aNbElems);
-       myMed->SetCellInfo(aCellInfo);
-      }
-      if(TInt aNbElems = anPyraElemNums.size()){
-       PCellInfo aCellInfo = myMed->CrCellInfo(aMeshInfo,
-                                               SMDS_MED_ENTITY,
-                                               ePYRA5,
-                                               aPyraConn,
-                                               SMDS_MED_CONNECTIVITY,
-                                               aPyraFamilyNums,
-                                               anPyraElemNums);
-       MESSAGE("Perform - anEntity = "<<SMDS_MED_ENTITY<<"; aGeom = "<<ePYRA5<<"; aNbElems = "<<aNbElems);
-       myMed->SetCellInfo(aCellInfo);
-      }
-      if(TInt aNbElems = anPentaElemNums.size()){
-       PCellInfo aCellInfo = myMed->CrCellInfo(aMeshInfo,
-                                               SMDS_MED_ENTITY,
-                                               ePENTA6,
-                                               aPentaConn,
-                                               SMDS_MED_CONNECTIVITY,
-                                               aPentaFamilyNums,
-                                               anPentaElemNums);
-       MESSAGE("Perform - anEntity = "<<SMDS_MED_ENTITY<<"; aGeom = "<<ePENTA6<<"; aNbElems = "<<aNbElems);
-       myMed->SetCellInfo(aCellInfo);
-      }
-      if(TInt aNbElems = aHexaElemNums.size()){
-       PCellInfo aCellInfo = myMed->CrCellInfo(aMeshInfo,
-                                               SMDS_MED_ENTITY,
-                                               eHEXA8,
-                                               aHexaConn,
-                                               SMDS_MED_CONNECTIVITY,
-                                               aHexaFamilyNums,
-                                               aHexaElemNums);
-       MESSAGE("Perform - anEntity = "<<SMDS_MED_ENTITY<<"; aGeom = "<<eHEXA8<<"; aNbElems = "<<aNbElems);
-       myMed->SetCellInfo(aCellInfo);
-      }
-      if(TInt aNbElems = anTetra10ElemNums.size()){
-       PCellInfo aCellInfo = myMed->CrCellInfo(aMeshInfo,
-                                               SMDS_MED_ENTITY,
-                                               eTETRA10,
-                                               aTetra10Conn,
-                                               SMDS_MED_CONNECTIVITY,
-                                               aTetra10FamilyNums,
-                                               anTetra10ElemNums);
-       MESSAGE("Perform - anEntity = "<<SMDS_MED_ENTITY<<"; aGeom = "<<eTETRA10<<"; aNbElems = "<<aNbElems);
-       myMed->SetCellInfo(aCellInfo);
-      }
-      if(TInt aNbElems = anPyra13ElemNums.size()){
-       PCellInfo aCellInfo = myMed->CrCellInfo(aMeshInfo,
-                                               SMDS_MED_ENTITY,
-                                               ePYRA13,
-                                               aPyra13Conn,
-                                               SMDS_MED_CONNECTIVITY,
-                                               aPyra13FamilyNums,
-                                               anPyra13ElemNums);
-       MESSAGE("Perform - anEntity = "<<SMDS_MED_ENTITY<<"; aGeom = "<<ePYRA13<<"; aNbElems = "<<aNbElems);
-       myMed->SetCellInfo(aCellInfo);
-      }
-      if(TInt aNbElems = anPenta15ElemNums.size()){
-       PCellInfo aCellInfo = myMed->CrCellInfo(aMeshInfo,
-                                               SMDS_MED_ENTITY,
-                                               ePENTA15,
-                                               aPenta15Conn,
-                                               SMDS_MED_CONNECTIVITY,
-                                               aPenta15FamilyNums,
-                                               anPenta15ElemNums);
-       MESSAGE("Perform - anEntity = "<<SMDS_MED_ENTITY<<"; aGeom = "<<ePENTA15<<"; aNbElems = "<<aNbElems);
-       myMed->SetCellInfo(aCellInfo);
-      }
-      if(TInt aNbElems = aHexa20ElemNums.size()){
-       PCellInfo aCellInfo = myMed->CrCellInfo(aMeshInfo,
-                                               SMDS_MED_ENTITY,
-                                               eHEXA20,
-                                               aHexa20Conn,
-                                               SMDS_MED_CONNECTIVITY,
-                                               aHexa20FamilyNums,
-                                               aHexa20ElemNums);
-       MESSAGE("Perform - anEntity = "<<SMDS_MED_ENTITY<<"; aGeom = "<<eHEXA20<<"; aNbElems = "<<aNbElems);
-       myMed->SetCellInfo(aCellInfo);
-      }
+    } // loop on geom types
+
 
-      if(TInt aNbElems = aPolyedreElemNums.size()){
-        // add one element in connectivities,
-        // referenced by the last element in faces
-        aPolyedreConn.push_back(0);
-
-       PPolyedreInfo aCellInfo = myMed->CrPolyedreInfo(aMeshInfo,
-                                                        SMDS_MED_ENTITY,
-                                                        ePOLYEDRE,
-                                                        aPolyedreInds,
-                                                        aPolyedreFaces,
-                                                        aPolyedreConn,
-                                                        SMDS_MED_CONNECTIVITY,
-                                                        aPolyedreFamilyNums,
-                                                        aPolyedreElemNums);
-       MESSAGE("Perform - anEntity = "<<SMDS_MED_ENTITY<<"; aGeom = "<<ePOLYEDRE<<"; aNbElems = "<<aNbElems);
-       myMed->SetPolyedreInfo(aCellInfo);
-      }
-    }
   }
   catch(const std::exception& exc) {
-    INFOS("Follow exception was cought:\n\t"<<exc.what());
+    INFOS("The following exception was caught:\n\t"<<exc.what());
     throw;
   }
   catch(...) {
-    INFOS("Unknown exception was cought !!!");
+    INFOS("Unknown exception was caught !!!");
     throw;
   }
 
@@ -1038,3 +975,31 @@ Driver_Mesh::Status DriverMED_W_SMESHDS_Mesh::Perform()
   mySubMeshes.clear();
   return aResult;
 }
+
+//================================================================================
+/*!
+ * \brief Returns nodes on VERTEXes where 0D elements are absent
+ */
+//================================================================================
+
+bool DriverMED_W_SMESHDS_Mesh::
+getNodesOfMissing0DOnVert(SMESHDS_Mesh*                         meshDS,
+                          std::vector<const SMDS_MeshElement*>& nodes)
+{
+  nodes.clear();
+  for ( int i = 1; i <= meshDS->MaxShapeIndex(); ++i )
+  {
+    if ( meshDS->IndexToShape( i ).ShapeType() != TopAbs_VERTEX )
+      continue;
+    if ( SMESHDS_SubMesh* sm = meshDS->MeshElements(i) ) {
+      SMDS_NodeIteratorPtr nIt= sm->GetNodes();
+      while (nIt->more())
+      {
+        const SMDS_MeshNode* n = nIt->next();
+        if ( n->NbInverseElements( SMDSAbs_0DElement ) == 0 )
+          nodes.push_back( n );
+      }
+    }
+  }
+  return !nodes.empty();
+}