Salome HOME
980a648d03b6d8d33736ac13eb29fcd12fafbd83
[modules/smesh.git] / src / DriverMED / DriverMED_W_SMESHDS_Mesh.cxx
1 //  SMESH DriverMED : driver to read and write 'med' files
2 //
3 //  Copyright (C) 2003  OPEN CASCADE, EADS/CCR, LIP6, CEA/DEN,
4 //  CEDRAT, EDF R&D, LEG, PRINCIPIA R&D, BUREAU VERITAS 
5 // 
6 //  This library is free software; you can redistribute it and/or 
7 //  modify it under the terms of the GNU Lesser General Public 
8 //  License as published by the Free Software Foundation; either 
9 //  version 2.1 of the License. 
10 // 
11 //  This library is distributed in the hope that it will be useful, 
12 //  but WITHOUT ANY WARRANTY; without even the implied warranty of 
13 //  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU 
14 //  Lesser General Public License for more details. 
15 // 
16 //  You should have received a copy of the GNU Lesser General Public 
17 //  License along with this library; if not, write to the Free Software 
18 //  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA 
19 // 
20 //  See http://www.opencascade.org/SALOME/ or email : webmaster.salome@opencascade.org 
21 //
22 //
23 //
24 //  File   : DriverMED_W_SMESHDS_Mesh.cxx
25 //  Module : SMESH
26
27 #include <sstream>
28
29 #include "DriverMED_W_SMESHDS_Mesh.h"
30 #include "DriverMED_W_SMDS_Mesh.h"
31 #include "DriverMED_Family.h"
32
33 #include "SMESHDS_Mesh.hxx"
34 #include "SMDS_MeshElement.hxx"
35 #include "SMDS_MeshNode.hxx"
36 #include "SMDS_PolyhedralVolumeOfNodes.hxx"
37
38 #include "utilities.h"
39
40 #include "MED_Utilities.hxx"
41
42 #define _EDF_NODE_IDS_
43 //#define _ELEMENTS_BY_DIM_
44
45 using namespace std;
46 using namespace MED;
47
48
49 DriverMED_W_SMESHDS_Mesh::DriverMED_W_SMESHDS_Mesh():
50   myAllSubMeshes (false),
51   myDoGroupOfNodes (false),
52   myDoGroupOfEdges (false),
53   myDoGroupOfFaces (false),
54   myDoGroupOfVolumes (false)
55 {}
56
57 void DriverMED_W_SMESHDS_Mesh::SetFile(const std::string& theFileName, 
58                                        MED::EVersion theId)
59 {
60   myMed = CrWrapper(theFileName,theId);
61   Driver_SMESHDS_Mesh::SetFile(theFileName);
62 }
63
64 void DriverMED_W_SMESHDS_Mesh::SetFile(const std::string& theFileName)
65 {
66   return SetFile(theFileName,MED::eV2_2);
67 }
68
69 void DriverMED_W_SMESHDS_Mesh::SetMeshName(const std::string& theMeshName)
70 {
71   myMeshName = theMeshName;
72 }
73
74 void DriverMED_W_SMESHDS_Mesh::AddGroup(SMESHDS_GroupBase* theGroup)
75 {
76   myGroups.push_back(theGroup);
77 }
78
79 void DriverMED_W_SMESHDS_Mesh::AddAllSubMeshes()
80 {
81   myAllSubMeshes = true;
82 }
83
84 void DriverMED_W_SMESHDS_Mesh::AddSubMesh(SMESHDS_SubMesh* theSubMesh, int theID)
85 {
86   mySubMeshes[theID] = theSubMesh;
87 }
88
89 void DriverMED_W_SMESHDS_Mesh::AddGroupOfNodes()
90 {
91   myDoGroupOfNodes = true;
92 }
93
94 void DriverMED_W_SMESHDS_Mesh::AddGroupOfEdges()
95 {
96   myDoGroupOfEdges = true;
97 }
98
99 void DriverMED_W_SMESHDS_Mesh::AddGroupOfFaces()
100 {
101   myDoGroupOfFaces = true;
102 }
103
104 void DriverMED_W_SMESHDS_Mesh::AddGroupOfVolumes()
105 {
106   myDoGroupOfVolumes = true;
107 }
108
109 namespace{
110   typedef double (SMDS_MeshNode::* TGetCoord)() const;
111   typedef const char* TName;
112   typedef const char* TUnit;
113
114   // name length in a mesh must be equal to 16 :
115   //         1234567890123456
116   TName M = "m               ";
117   TName X = "x               ";
118   TName Y = "y               ";
119   TName Z = "z               ";
120
121   TUnit aUnit[3] = {M,M,M};
122
123   // 3 dim
124   TGetCoord aXYZGetCoord[3] = {
125     &SMDS_MeshNode::X, 
126     &SMDS_MeshNode::Y, 
127     &SMDS_MeshNode::Z
128   };
129   TName aXYZName[3] = {X,Y,Z};
130   
131   // 2 dim
132   TGetCoord aXYGetCoord[2] = {
133     &SMDS_MeshNode::X, 
134     &SMDS_MeshNode::Y
135   };
136   TName aXYName[2] = {X,Y};
137
138   TGetCoord aYZGetCoord[2] = {
139     &SMDS_MeshNode::Y, 
140     &SMDS_MeshNode::Z
141   };
142   TName aYZName[2] = {Y,Z};
143
144   TGetCoord aXZGetCoord[2] = {
145     &SMDS_MeshNode::X, 
146     &SMDS_MeshNode::Z
147   };
148   TName aXZName[2] = {X,Z};
149
150   // 1 dim
151   TGetCoord aXGetCoord[1] = {
152     &SMDS_MeshNode::X
153   };
154   TName aXName[1] = {X};
155
156   TGetCoord aYGetCoord[1] = {
157     &SMDS_MeshNode::Y
158   };
159   TName aYName[1] = {Y};
160
161   TGetCoord aZGetCoord[1] = {
162     &SMDS_MeshNode::Z
163   };
164   TName aZName[1] = {Z};
165
166
167   class TCoordHelper{
168     SMDS_NodeIteratorPtr myNodeIter;
169     const SMDS_MeshNode* myCurrentNode;
170     TGetCoord* myGetCoord;
171     TName* myName;
172     TUnit* myUnit;
173   public:
174     TCoordHelper(const SMDS_NodeIteratorPtr& theNodeIter,
175                  TGetCoord* theGetCoord,
176                  TName* theName,
177                  TUnit* theUnit = aUnit):
178       myNodeIter(theNodeIter),
179       myGetCoord(theGetCoord),
180       myName(theName),
181       myUnit(theUnit)
182     {}
183     virtual ~TCoordHelper(){}
184     bool Next(){ 
185       return myNodeIter->more() && 
186         (myCurrentNode = myNodeIter->next());
187     }
188     const SMDS_MeshNode* GetNode(){
189       return myCurrentNode;
190     }
191     MED::TIntVector::value_type GetID(){
192       return myCurrentNode->GetID();
193     }
194     MED::TFloatVector::value_type GetCoord(TInt theCoodId){
195       return (myCurrentNode->*myGetCoord[theCoodId])();
196     }
197     MED::TStringVector::value_type GetName(TInt theDimId){
198       return myName[theDimId];
199     }
200     MED::TStringVector::value_type GetUnit(TInt theDimId){
201       return myUnit[theDimId];
202     }
203   };
204   typedef boost::shared_ptr<TCoordHelper> TCoordHelperPtr;
205   
206 }
207
208   
209 Driver_Mesh::Status DriverMED_W_SMESHDS_Mesh::Perform()
210 {
211   Status aResult = DRS_OK;
212   if (myMesh->hasConstructionEdges() || myMesh->hasConstructionFaces()) {
213     INFOS("SMDS_MESH with hasConstructionEdges() or hasConstructionFaces() do not supports!!!");
214     return DRS_FAIL;
215   }
216   try{
217     MESSAGE("Perform - myFile : "<<myFile);
218
219     // Creating the MED mesh for corresponding SMDS structure
220     //-------------------------------------------------------
221     string aMeshName;
222     if (myMeshId != -1) {
223       ostringstream aMeshNameStr;
224       aMeshNameStr<<myMeshId;
225       aMeshName = aMeshNameStr.str();
226     } else {
227       aMeshName = myMeshName;
228     }
229
230     // Mesh dimension definition
231     TInt aMeshDimension;
232     TCoordHelperPtr aCoordHelperPtr;
233     {  
234       bool anIsXDimension = false;
235       bool anIsYDimension = false;
236       bool anIsZDimension = false;
237       {
238         SMDS_NodeIteratorPtr aNodesIter = myMesh->nodesIterator();
239         double aBounds[6];
240         if(aNodesIter->more()){
241           const SMDS_MeshNode* aNode = aNodesIter->next();
242           aBounds[0] = aBounds[1] = aNode->X();
243           aBounds[2] = aBounds[3] = aNode->Y();
244           aBounds[4] = aBounds[5] = aNode->Z();
245         }
246         while(aNodesIter->more()){
247           const SMDS_MeshNode* aNode = aNodesIter->next();
248           aBounds[0] = min(aBounds[0],aNode->X());
249           aBounds[1] = max(aBounds[1],aNode->X());
250           
251           aBounds[2] = min(aBounds[2],aNode->Y());
252           aBounds[3] = max(aBounds[3],aNode->Y());
253           
254           aBounds[4] = min(aBounds[4],aNode->Z());
255           aBounds[5] = max(aBounds[5],aNode->Z());
256         }
257
258         double EPS = 1.0E-7;
259         anIsXDimension = (aBounds[1] - aBounds[0]) + abs(aBounds[1]) + abs(aBounds[0]) > EPS;
260         anIsYDimension = (aBounds[3] - aBounds[2]) + abs(aBounds[3]) + abs(aBounds[2]) > EPS;
261         anIsZDimension = (aBounds[5] - aBounds[4]) + abs(aBounds[5]) + abs(aBounds[4]) > EPS;
262         aMeshDimension = anIsXDimension + anIsYDimension + anIsZDimension;
263         if(!aMeshDimension)
264           aMeshDimension = 3;
265       }
266
267       SMDS_NodeIteratorPtr aNodesIter = myMesh->nodesIterator();
268       switch(aMeshDimension){
269       case 3:
270         aCoordHelperPtr.reset(new TCoordHelper(aNodesIter,aXYZGetCoord,aXYZName));
271         break;
272       case 2:
273         if(anIsXDimension && anIsYDimension)
274           aCoordHelperPtr.reset(new TCoordHelper(aNodesIter,aXYGetCoord,aXYName));
275         if(anIsYDimension && anIsZDimension)
276           aCoordHelperPtr.reset(new TCoordHelper(aNodesIter,aYZGetCoord,aYZName));
277         if(anIsXDimension && anIsZDimension)
278           aCoordHelperPtr.reset(new TCoordHelper(aNodesIter,aXZGetCoord,aXZName));
279         break;
280       case 1:
281         if(anIsXDimension)
282           aCoordHelperPtr.reset(new TCoordHelper(aNodesIter,aXGetCoord,aXName));
283         if(anIsYDimension)
284           aCoordHelperPtr.reset(new TCoordHelper(aNodesIter,aYGetCoord,aYName));
285         if(anIsZDimension)
286           aCoordHelperPtr.reset(new TCoordHelper(aNodesIter,aZGetCoord,aZName));
287         break;
288       }
289     }
290
291     
292     PMeshInfo aMeshInfo = myMed->CrMeshInfo(aMeshDimension,aMeshName);
293     MESSAGE("Add - aMeshName : "<<aMeshName<<"; "<<aMeshInfo->GetName());
294     myMed->SetMeshInfo(aMeshInfo);
295
296     // Storing SMDS groups and sub-meshes
297     //-----------------------------------
298     int myNodesDefaultFamilyId = 0;
299     int myEdgesDefaultFamilyId = 0;
300     int myFacesDefaultFamilyId = 0;
301     int myVolumesDefaultFamilyId = 0;
302     if (myDoGroupOfNodes)
303       myNodesDefaultFamilyId = REST_NODES_FAMILY;
304     if (myDoGroupOfEdges)
305       myEdgesDefaultFamilyId = REST_EDGES_FAMILY;
306     if (myDoGroupOfFaces)
307       myFacesDefaultFamilyId = REST_FACES_FAMILY;
308     if (myDoGroupOfVolumes)
309       myVolumesDefaultFamilyId = REST_VOLUMES_FAMILY;
310
311     MESSAGE("Perform - aFamilyInfo");
312     map<const SMDS_MeshElement *, int> anElemFamMap;
313     list<DriverMED_FamilyPtr> aFamilies;
314     if (myAllSubMeshes) {
315       aFamilies = DriverMED_Family::MakeFamilies
316         (myMesh->SubMeshes(), myGroups,
317          myDoGroupOfNodes, myDoGroupOfEdges, myDoGroupOfFaces, myDoGroupOfVolumes);
318     } else {
319       aFamilies = DriverMED_Family::MakeFamilies
320         (mySubMeshes, myGroups,
321          myDoGroupOfNodes, myDoGroupOfEdges, myDoGroupOfFaces, myDoGroupOfVolumes);
322     }
323     list<DriverMED_FamilyPtr>::iterator aFamsIter = aFamilies.begin();
324
325     for (; aFamsIter != aFamilies.end(); aFamsIter++)
326     {
327       PFamilyInfo aFamilyInfo = (*aFamsIter)->GetFamilyInfo(myMed,aMeshInfo);
328       myMed->SetFamilyInfo(aFamilyInfo);
329       int aFamId = (*aFamsIter)->GetId();
330
331       const set<const SMDS_MeshElement *>& anElems = (*aFamsIter)->GetElements();
332           set<const SMDS_MeshElement *>::const_iterator anElemsIter = anElems.begin();
333       for (; anElemsIter != anElems.end(); anElemsIter++)
334       {
335         anElemFamMap[*anElemsIter] = aFamId;
336       }
337 //      delete (*aFamsIter);
338     }
339
340     // Storing SMDS nodes to the MED file for the MED mesh
341     //----------------------------------------------------
342 #ifdef _EDF_NODE_IDS_
343     typedef map<TInt,TInt> TNodeIdMap;
344     TNodeIdMap aNodeIdMap;
345 #endif
346     TInt aNbElems = myMesh->NbNodes();
347     MED::TIntVector anElemNums(aNbElems);
348     MED::TIntVector aFamilyNums(aNbElems);
349     MED::TFloatVector aCoordinates(aNbElems*aMeshDimension);
350     for(TInt iNode = 0, aStartId = 0; aCoordHelperPtr->Next(); iNode++, aStartId += aMeshDimension){
351       for(TInt iCoord = 0; iCoord < aMeshDimension; iCoord++){
352         aCoordinates[aStartId+iCoord] = aCoordHelperPtr->GetCoord(iCoord);
353       }
354       int aNodeID = aCoordHelperPtr->GetID();
355       anElemNums[iNode] = aNodeID;
356 #ifdef _EDF_NODE_IDS_
357       aNodeIdMap[aNodeID] = iNode+1;
358 #endif
359       const SMDS_MeshNode* aNode = aCoordHelperPtr->GetNode();
360       if (anElemFamMap.find(aNode) != anElemFamMap.end())
361         aFamilyNums[iNode] = anElemFamMap[aNode];
362       else
363         aFamilyNums[iNode] = myNodesDefaultFamilyId;
364     }
365
366     MED::TStringVector aCoordNames(aMeshDimension);
367     MED::TStringVector aCoordUnits(aMeshDimension);
368     for(TInt iCoord = 0; iCoord < aMeshDimension; iCoord++){
369       aCoordNames[iCoord] = aCoordHelperPtr->GetName(iCoord);
370       aCoordUnits[iCoord] = aCoordHelperPtr->GetUnit(iCoord);
371     }
372
373     const ERepere SMDS_COORDINATE_SYSTEM = eCART;
374
375     PNodeInfo aNodeInfo = myMed->CrNodeInfo(aMeshInfo,
376                                             SMDS_COORDINATE_SYSTEM,
377                                             aCoordinates,
378                                             aCoordNames,
379                                             aCoordUnits,
380                                             aFamilyNums,
381                                             anElemNums);
382     MESSAGE("Perform - aNodeInfo->GetNbElem() = "<<aNbElems);
383     myMed->SetNodeInfo(aNodeInfo);
384
385
386     // Storing others SMDS elements to the MED file for the MED mesh
387     //--------------------------------------------------------------
388     EEntiteMaillage SMDS_MED_ENTITY = eMAILLE;
389     const EConnectivite SMDS_MED_CONNECTIVITY = eNOD;
390
391     // Storing SMDS Edges
392     if(TInt aNbElems = myMesh->NbEdges()){
393 #ifdef _ELEMENTS_BY_DIM_
394       SMDS_MED_ENTITY = eARETE;
395 #endif
396       SMDS_EdgeIteratorPtr anIter = myMesh->edgesIterator();
397       TInt aNbConnectivity = MED::GetNbNodes(eSEG2);
398       MED::TIntVector anElemNums(aNbElems);
399       MED::TIntVector aFamilyNums(aNbElems);
400       MED::TIntVector aConnectivity(aNbElems*aNbConnectivity);
401
402       for(TInt iElem = 0, iConn = 0; anIter->more(); iElem++, iConn+=aNbConnectivity){
403         const SMDS_MeshEdge* anElem = anIter->next();
404         SMDS_ElemIteratorPtr aNodesIter = anElem->nodesIterator();
405         for(TInt iNode = 0; iNode < aNbConnectivity && aNodesIter->more(); iNode++){
406           const SMDS_MeshElement* aNode = aNodesIter->next();
407 #ifdef _EDF_NODE_IDS_
408           aConnectivity[iConn+iNode] = aNodeIdMap[aNode->GetID()];
409 #else
410           aConnectivity[iConn+iNode] = aNode->GetID();
411 #endif
412         }
413         anElemNums[iElem] = anElem->GetID();
414
415         if (anElemFamMap.find(anElem) != anElemFamMap.end())
416           aFamilyNums[iElem] = anElemFamMap[anElem];
417         else
418           aFamilyNums[iElem] = myEdgesDefaultFamilyId;
419       }
420       
421       PCellInfo aCellInfo = myMed->CrCellInfo(aMeshInfo,
422                                               SMDS_MED_ENTITY,
423                                               eSEG2,
424                                               SMDS_MED_CONNECTIVITY,
425                                               aConnectivity,
426                                               aFamilyNums,
427                                               anElemNums);
428       myMed->SetCellInfo(aCellInfo);
429     }
430
431     // Storing SMDS Faces
432     if(TInt aNbElems = myMesh->NbFaces()){
433       SMDS_FaceIteratorPtr anIter = myMesh->facesIterator();
434 #ifdef _ELEMENTS_BY_DIM_
435       SMDS_MED_ENTITY = eFACE;
436 #endif
437       TInt aNbTriaConn = MED::GetNbNodes(eTRIA3);
438       MED::TIntVector anTriaElemNums; 
439       anTriaElemNums.reserve(aNbElems);
440       MED::TIntVector aTriaFamilyNums;
441       aTriaFamilyNums.reserve(aNbElems);
442       MED::TIntVector aTriaConn;
443       aTriaConn.reserve(aNbElems*aNbTriaConn);
444
445       TInt aNbQuadConn = MED::GetNbNodes(eQUAD4);
446       MED::TIntVector aQuadElemNums;
447       aQuadElemNums.reserve(aNbElems);
448       MED::TIntVector aQuadFamilyNums;
449       aQuadFamilyNums.reserve(aNbElems);
450       MED::TIntVector aQuadConn;
451       aQuadConn.reserve(aNbElems*aNbQuadConn);
452
453       MED::TIntVector aPolygoneElemNums;
454       aPolygoneElemNums.reserve(aNbElems);
455       MED::TIntVector aPolygoneInds;
456       aPolygoneInds.reserve(aNbElems + 1);
457       aPolygoneInds.push_back(1); // reference on the first element in the connectivities
458       MED::TIntVector aPolygoneFamilyNums;
459       aPolygoneFamilyNums.reserve(aNbElems);
460       MED::TIntVector aPolygoneConn;
461       aPolygoneConn.reserve(aNbElems*aNbQuadConn);
462
463       for(TInt iElem = 0; iElem < aNbElems && anIter->more(); iElem++){
464         const SMDS_MeshFace* anElem = anIter->next();
465         TInt aNbNodes = anElem->NbNodes();
466         SMDS_ElemIteratorPtr aNodesIter = anElem->nodesIterator();
467         TInt aNbConnectivity;
468         MED::TIntVector* anElemNums;
469         MED::TIntVector* aFamilyNums;
470         MED::TIntVector* aConnectivity;
471         if (anElem->IsPoly()) {
472           aNbConnectivity = aNbNodes;
473           anElemNums = &aPolygoneElemNums;
474           aFamilyNums = &aPolygoneFamilyNums;
475           aConnectivity = &aPolygoneConn;
476         } else {
477           switch(aNbNodes){
478           case 3:
479             aNbConnectivity = aNbTriaConn;
480             anElemNums = &anTriaElemNums;
481             aFamilyNums = &aTriaFamilyNums;
482             aConnectivity = &aTriaConn;
483             break;
484           case 4:
485             aNbConnectivity = aNbQuadConn;
486             anElemNums = &aQuadElemNums;
487             aFamilyNums = &aQuadFamilyNums;
488             aConnectivity = &aQuadConn;
489             break;
490           default:
491             break;
492           }
493         }
494         MED::TIntVector aVector(aNbNodes);
495         for(TInt iNode = 0; aNodesIter->more(); iNode++){
496           const SMDS_MeshElement* aNode = aNodesIter->next();
497 #ifdef _EDF_NODE_IDS_
498           aVector[iNode] = aNodeIdMap[aNode->GetID()];
499 #else
500           aVector[iNode] = aNode->GetID();
501 #endif
502         }
503
504         TInt aSize = aConnectivity->size();
505         aConnectivity->resize(aSize+aNbConnectivity);
506         // There is some differences between SMDS and MED in cells mapping
507         switch(aNbNodes){
508         case 4:
509           (*aConnectivity)[aSize+0] = aVector[0];
510           (*aConnectivity)[aSize+1] = aVector[1];
511           (*aConnectivity)[aSize+2] = aVector[3];  
512           (*aConnectivity)[aSize+3] = aVector[2];  
513         default:
514           for(TInt iNode = 0; iNode < aNbNodes; iNode++) 
515             (*aConnectivity)[aSize+iNode] = aVector[iNode];
516         }
517
518         if (anElem->IsPoly()) {
519           // fill indices for polygonal element
520           TInt aPrevPos = aPolygoneInds.back();
521           aPolygoneInds.push_back(aPrevPos + aNbNodes);
522         }
523
524         anElemNums->push_back(anElem->GetID());
525
526         if (anElemFamMap.find(anElem) != anElemFamMap.end())
527           aFamilyNums->push_back(anElemFamMap[anElem]);
528         else
529           aFamilyNums->push_back(myFacesDefaultFamilyId);
530       }
531       if(TInt aNbElems = anTriaElemNums.size()){
532         PCellInfo aCellInfo = myMed->CrCellInfo(aMeshInfo,
533                                                 SMDS_MED_ENTITY,
534                                                 eTRIA3,
535                                                 SMDS_MED_CONNECTIVITY,
536                                                 aTriaConn,
537                                                 aTriaFamilyNums,
538                                                 anTriaElemNums);
539         MESSAGE("Perform - anEntity = "<<SMDS_MED_ENTITY<<"; aGeom = "<<eTRIA3<<"; aNbElems = "<<aNbElems);
540         myMed->SetCellInfo(aCellInfo);
541       }
542       if(TInt aNbElems = aQuadElemNums.size()){
543         PCellInfo aCellInfo = myMed->CrCellInfo(aMeshInfo,
544                                                 SMDS_MED_ENTITY,
545                                                 eQUAD4,
546                                                 SMDS_MED_CONNECTIVITY,
547                                                 aQuadConn,
548                                                 aQuadFamilyNums,
549                                                 aQuadElemNums);
550         MESSAGE("Perform - anEntity = "<<SMDS_MED_ENTITY<<"; aGeom = "<<eQUAD4<<"; aNbElems = "<<aNbElems);
551         myMed->SetCellInfo(aCellInfo);
552       }
553       if(TInt aNbElems = aPolygoneElemNums.size()){
554         // add one element in connectivities,
555         // referenced by the last element in indices
556         aPolygoneConn.push_back(0);
557
558         PPolygoneInfo aCellInfo = myMed->CrPolygoneInfo(aMeshInfo,
559                                                         SMDS_MED_ENTITY,
560                                                         ePOLYGONE,
561                                                         SMDS_MED_CONNECTIVITY,
562                                                         aPolygoneConn,
563                                                         aPolygoneInds,
564                                                         aPolygoneFamilyNums,
565                                                         aPolygoneElemNums);
566         MESSAGE("Perform - anEntity = "<<SMDS_MED_ENTITY<<"; aGeom = "<<ePOLYGONE<<"; aNbElems = "<<aNbElems);
567         myMed->SetPolygoneInfo(aCellInfo);
568       }
569     }
570
571     // Storing SMDS Volumes
572     if(TInt aNbElems = myMesh->NbVolumes()){
573       SMDS_VolumeIteratorPtr anIter = myMesh->volumesIterator();
574 #ifdef _ELEMENTS_BY_DIM_
575       SMDS_MED_ENTITY = eMAILLE;
576 #endif
577       TInt aNbTetraConn = MED::GetNbNodes(eTETRA4);
578       MED::TIntVector anTetraElemNums; 
579       anTetraElemNums.reserve(aNbElems);
580       MED::TIntVector aTetraFamilyNums;
581       aTetraFamilyNums.reserve(aNbElems);
582       MED::TIntVector aTetraConn;
583       aTetraConn.reserve(aNbElems*aNbTetraConn);
584
585       TInt aNbPyraConn = MED::GetNbNodes(ePYRA5);
586       MED::TIntVector anPyraElemNums; 
587       anPyraElemNums.reserve(aNbElems);
588       MED::TIntVector aPyraFamilyNums;
589       aPyraFamilyNums.reserve(aNbElems);
590       MED::TIntVector aPyraConn;
591       aPyraConn.reserve(aNbElems*aNbPyraConn);
592
593       TInt aNbPentaConn = MED::GetNbNodes(ePENTA6);
594       MED::TIntVector anPentaElemNums; 
595       anPentaElemNums.reserve(aNbElems);
596       MED::TIntVector aPentaFamilyNums;
597       aPentaFamilyNums.reserve(aNbElems);
598       MED::TIntVector aPentaConn;
599       aPentaConn.reserve(aNbElems*aNbPentaConn);
600
601       TInt aNbHexaConn = MED::GetNbNodes(eHEXA8);
602       MED::TIntVector aHexaElemNums;
603       aHexaElemNums.reserve(aNbElems);
604       MED::TIntVector aHexaFamilyNums;
605       aHexaFamilyNums.reserve(aNbElems);
606       MED::TIntVector aHexaConn;
607       aHexaConn.reserve(aNbElems*aNbHexaConn);
608
609       MED::TIntVector aPolyedreElemNums;
610       aPolyedreElemNums.reserve(aNbElems);
611       MED::TIntVector aPolyedreInds;
612       aPolyedreInds.reserve(aNbElems + 1);
613       aPolyedreInds.push_back(1); // reference on the first element in the faces
614       MED::TIntVector aPolyedreFaces;
615       aPolyedreFaces.reserve(aNbElems + 1);
616       aPolyedreFaces.push_back(1); // reference on the first element in the connectivities
617       MED::TIntVector aPolyedreFamilyNums;
618       aPolyedreFamilyNums.reserve(aNbElems);
619       MED::TIntVector aPolyedreConn;
620       aPolyedreConn.reserve(aNbElems*aNbHexaConn);
621
622       for(TInt iElem = 0; iElem < aNbElems && anIter->more(); iElem++){
623         const SMDS_MeshVolume* anElem = anIter->next();
624
625         MED::TIntVector* anElemNums;
626         MED::TIntVector* aFamilyNums;
627
628         if (anElem->IsPoly()) {
629           const SMDS_PolyhedralVolumeOfNodes* aPolyedre =
630             (const SMDS_PolyhedralVolumeOfNodes*) anElem;
631           if (!aPolyedre) {
632             MESSAGE("Warning: bad volumic element");
633             continue;
634           }
635
636           anElemNums = &aPolyedreElemNums;
637           aFamilyNums = &aPolyedreFamilyNums;
638
639           TInt aNodeId, aNbFaces = aPolyedre->NbFaces();
640           for (int iface = 1; iface <= aNbFaces; iface++) {
641             int aNbFaceNodes = aPolyedre->NbFaceNodes(iface);
642             for (int inode = 1; inode <= aNbFaceNodes; inode++) {
643               aNodeId = aPolyedre->GetFaceNode(iface, inode)->GetID();
644 #ifdef _EDF_NODE_IDS_
645               aPolyedreConn.push_back(aNodeIdMap[aNodeId]);
646 #else
647               aPolyedreConn.push_back(aNodeId);
648 #endif
649             }
650             TInt aPrevPos = aPolyedreFaces.back();
651             aPolyedreFaces.push_back(aPrevPos + aNbFaceNodes);
652           }
653           TInt aPrevPos = aPolyedreInds.back();
654           aPolyedreInds.push_back(aPrevPos + aNbFaces);
655
656         } else {
657           TInt aNbNodes = anElem->NbNodes();
658           SMDS_ElemIteratorPtr aNodesIter = anElem->nodesIterator();
659           TInt aNbConnectivity;
660           MED::TIntVector* aConnectivity;
661           switch(aNbNodes){
662           case 4:
663             aNbConnectivity = aNbTetraConn;
664             anElemNums = &anTetraElemNums;
665             aFamilyNums = &aTetraFamilyNums;
666             aConnectivity = &aTetraConn;
667             break;
668           case 5:
669             aNbConnectivity = aNbPyraConn;
670             anElemNums = &anPyraElemNums;
671             aFamilyNums = &aPyraFamilyNums;
672             aConnectivity = &aPyraConn;
673             break;
674           case 6:
675             aNbConnectivity = aNbPentaConn;
676             anElemNums = &anPentaElemNums;
677             aFamilyNums = &aPentaFamilyNums;
678             aConnectivity = &aPentaConn;
679             break;
680           case 8:
681             aNbConnectivity = aNbHexaConn;
682             anElemNums = &aHexaElemNums;
683             aFamilyNums = &aHexaFamilyNums;
684             aConnectivity = &aHexaConn;
685           }
686
687           TInt aSize = aConnectivity->size();
688           aConnectivity->resize(aSize + aNbConnectivity);
689
690           MED::TIntVector aVector(aNbNodes);
691           for(TInt iNode = 0; aNodesIter->more(); iNode++){
692             const SMDS_MeshElement* aNode = aNodesIter->next();
693 #ifdef _EDF_NODE_IDS_
694             aVector[iNode] = aNodeIdMap[aNode->GetID()];
695 #else
696             aVector[iNode] = aNode->GetID();
697 #endif
698           }
699           // There is some difference between SMDS and MED in cells mapping
700           switch(aNbNodes){
701           case 5:
702             (*aConnectivity)[aSize+0] = aVector[0];
703             (*aConnectivity)[aSize+1] = aVector[3];
704             (*aConnectivity)[aSize+2] = aVector[2];  
705             (*aConnectivity)[aSize+3] = aVector[1];  
706             (*aConnectivity)[aSize+4] = aVector[4];  
707           default:
708             for(TInt iNode = 0; iNode < aNbNodes; iNode++) 
709               (*aConnectivity)[aSize+iNode] = aVector[iNode];
710           }
711         }
712
713         anElemNums->push_back(anElem->GetID());
714
715         if (anElemFamMap.find(anElem) != anElemFamMap.end())
716           aFamilyNums->push_back(anElemFamMap[anElem]);
717         else
718           aFamilyNums->push_back(myVolumesDefaultFamilyId);
719       }
720
721       if(TInt aNbElems = anTetraElemNums.size()){
722         PCellInfo aCellInfo = myMed->CrCellInfo(aMeshInfo,
723                                                 SMDS_MED_ENTITY,
724                                                 eTETRA4,
725                                                 SMDS_MED_CONNECTIVITY,
726                                                 aTetraConn,
727                                                 aTetraFamilyNums,
728                                                 anTetraElemNums);
729         MESSAGE("Perform - anEntity = "<<SMDS_MED_ENTITY<<"; aGeom = "<<eTETRA4<<"; aNbElems = "<<aNbElems);
730         myMed->SetCellInfo(aCellInfo);
731       }
732       if(TInt aNbElems = anPyraElemNums.size()){
733         PCellInfo aCellInfo = myMed->CrCellInfo(aMeshInfo,
734                                                 SMDS_MED_ENTITY,
735                                                 ePYRA5,
736                                                 SMDS_MED_CONNECTIVITY,
737                                                 aPyraConn,
738                                                 aPyraFamilyNums,
739                                                 anPyraElemNums);
740         MESSAGE("Perform - anEntity = "<<SMDS_MED_ENTITY<<"; aGeom = "<<ePYRA5<<"; aNbElems = "<<aNbElems);
741         myMed->SetCellInfo(aCellInfo);
742       }
743       if(TInt aNbElems = anPentaElemNums.size()){
744         PCellInfo aCellInfo = myMed->CrCellInfo(aMeshInfo,
745                                                 SMDS_MED_ENTITY,
746                                                 ePENTA6,
747                                                 SMDS_MED_CONNECTIVITY,
748                                                 aPentaConn,
749                                                 aPentaFamilyNums,
750                                                 anPentaElemNums);
751         MESSAGE("Perform - anEntity = "<<SMDS_MED_ENTITY<<"; aGeom = "<<ePENTA6<<"; aNbElems = "<<aNbElems);
752         myMed->SetCellInfo(aCellInfo);
753       }
754       if(TInt aNbElems = aHexaElemNums.size()){
755         PCellInfo aCellInfo = myMed->CrCellInfo(aMeshInfo,
756                                                 SMDS_MED_ENTITY,
757                                                 eHEXA8,
758                                                 SMDS_MED_CONNECTIVITY,
759                                                 aHexaConn,
760                                                 aHexaFamilyNums,
761                                                 aHexaElemNums);
762         MESSAGE("Perform - anEntity = "<<SMDS_MED_ENTITY<<"; aGeom = "<<eHEXA8<<"; aNbElems = "<<aNbElems);
763         myMed->SetCellInfo(aCellInfo);
764       }
765       if(TInt aNbElems = aPolyedreElemNums.size()){
766         // add one element in connectivities,
767         // referenced by the last element in faces
768         aPolyedreConn.push_back(0);
769
770         PPolyedreInfo aCellInfo = myMed->CrPolyedreInfo(aMeshInfo,
771                                                         SMDS_MED_ENTITY,
772                                                         ePOLYEDRE,
773                                                         SMDS_MED_CONNECTIVITY,
774                                                         aPolyedreConn,
775                                                         aPolyedreFaces,
776                                                         aPolyedreInds,
777                                                         aPolyedreFamilyNums,
778                                                         aPolyedreElemNums);
779         MESSAGE("Perform - anEntity = "<<SMDS_MED_ENTITY<<"; aGeom = "<<ePOLYEDRE<<"; aNbElems = "<<aNbElems);
780         myMed->SetPolyedreInfo(aCellInfo);
781       }
782     }
783   }catch(const std::exception& exc){
784     INFOS("Follow exception was cought:\n\t"<<exc.what());
785   }catch(...){
786     INFOS("Unknown exception was cought !!!");
787   }
788
789   myMeshId = -1;
790   myGroups.clear();
791   mySubMeshes.clear();
792   return aResult;
793 }