Salome HOME
To port on new version of MEDWrapper
[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   TUnit aUnit[3] = {"m","m","m"};
115
116   TGetCoord aXYZGetCoord[3] = {
117     &SMDS_MeshNode::X, 
118     &SMDS_MeshNode::Y, 
119     &SMDS_MeshNode::Z
120   };
121   TName aXYZName[3] = {"x","y","z"};
122   
123   
124   TGetCoord aXYGetCoord[2] = {
125     &SMDS_MeshNode::X, 
126     &SMDS_MeshNode::Y
127   };
128   TName aXYName[2] = {"x","y"};
129
130   TGetCoord aYZGetCoord[2] = {
131     &SMDS_MeshNode::Y, 
132     &SMDS_MeshNode::Z
133   };
134   TName aYZName[2] = {"y","z"};
135
136   TGetCoord aXZGetCoord[2] = {
137     &SMDS_MeshNode::X, 
138     &SMDS_MeshNode::Z
139   };
140   TName aXZName[2] = {"x","z"};
141
142
143   TGetCoord aXGetCoord[1] = {
144     &SMDS_MeshNode::X
145   };
146   TName aXName[1] = {"x"};
147
148   TGetCoord aYGetCoord[1] = {
149     &SMDS_MeshNode::Y
150   };
151   TName aYName[1] = {"y"};
152
153   TGetCoord aZGetCoord[1] = {
154     &SMDS_MeshNode::Z
155   };
156   TName aZName[1] = {"z"};
157
158
159   class TCoordHelper{
160     SMDS_NodeIteratorPtr myNodeIter;
161     const SMDS_MeshNode* myCurrentNode;
162     TGetCoord* myGetCoord;
163     TName* myName;
164     TUnit* myUnit;
165   public:
166     TCoordHelper(const SMDS_NodeIteratorPtr& theNodeIter,
167                  TGetCoord* theGetCoord,
168                  TName* theName,
169                  TUnit* theUnit = aUnit):
170       myNodeIter(theNodeIter),
171       myGetCoord(theGetCoord),
172       myName(theName),
173       myUnit(theUnit)
174     {}
175     virtual ~TCoordHelper(){}
176     bool Next(){ 
177       return myNodeIter->more() && 
178         (myCurrentNode = myNodeIter->next());
179     }
180     const SMDS_MeshNode* GetNode(){
181       return myCurrentNode;
182     }
183     MED::TIntVector::value_type GetID(){
184       return myCurrentNode->GetID();
185     }
186     MED::TFloatVector::value_type GetCoord(TInt theCoodId){
187       return (myCurrentNode->*myGetCoord[theCoodId])();
188     }
189     MED::TStringVector::value_type GetName(TInt theDimId){
190       return myName[theDimId];
191     }
192     MED::TStringVector::value_type GetUnit(TInt theDimId){
193       return myUnit[theDimId];
194     }
195   };
196   typedef boost::shared_ptr<TCoordHelper> TCoordHelperPtr;
197   
198 }
199
200   
201 Driver_Mesh::Status DriverMED_W_SMESHDS_Mesh::Perform()
202 {
203   Status aResult = DRS_OK;
204   if (myMesh->hasConstructionEdges() || myMesh->hasConstructionFaces()) {
205     INFOS("SMDS_MESH with hasConstructionEdges() or hasConstructionFaces() do not supports!!!");
206     return DRS_FAIL;
207   }
208   try{
209     MESSAGE("Perform - myFile : "<<myFile);
210
211     // Creating the MED mesh for corresponding SMDS structure
212     //-------------------------------------------------------
213     string aMeshName;
214     if (myMeshId != -1) {
215       ostringstream aMeshNameStr;
216       aMeshNameStr<<myMeshId;
217       aMeshName = aMeshNameStr.str();
218     } else {
219       aMeshName = myMeshName;
220     }
221
222     // Mesh dimension definition
223     TInt aMeshDimension;
224     TCoordHelperPtr aCoordHelperPtr;
225     {  
226       bool anIsXDimension = false;
227       bool anIsYDimension = false;
228       bool anIsZDimension = false;
229       {
230         SMDS_NodeIteratorPtr aNodesIter = myMesh->nodesIterator();
231         double aBounds[6];
232         if(aNodesIter->more()){
233           const SMDS_MeshNode* aNode = aNodesIter->next();
234           aBounds[0] = aBounds[1] = aNode->X();
235           aBounds[2] = aBounds[3] = aNode->Y();
236           aBounds[4] = aBounds[5] = aNode->Z();
237         }
238         while(aNodesIter->more()){
239           const SMDS_MeshNode* aNode = aNodesIter->next();
240           aBounds[0] = min(aBounds[0],aNode->X());
241           aBounds[1] = max(aBounds[1],aNode->X());
242           
243           aBounds[2] = min(aBounds[2],aNode->Y());
244           aBounds[3] = max(aBounds[3],aNode->Y());
245           
246           aBounds[4] = min(aBounds[4],aNode->Z());
247           aBounds[5] = max(aBounds[5],aNode->Z());
248         }
249
250         double EPS = 1.0E-7;
251         anIsXDimension = (aBounds[1] - aBounds[0]) + abs(aBounds[1]) + abs(aBounds[0]) > EPS;
252         anIsYDimension = (aBounds[3] - aBounds[2]) + abs(aBounds[3]) + abs(aBounds[2]) > EPS;
253         anIsZDimension = (aBounds[5] - aBounds[4]) + abs(aBounds[5]) + abs(aBounds[4]) > EPS;
254         aMeshDimension = anIsXDimension + anIsYDimension + anIsZDimension;
255         if(!aMeshDimension)
256           aMeshDimension = 3;
257       }
258
259       SMDS_NodeIteratorPtr aNodesIter = myMesh->nodesIterator();
260       switch(aMeshDimension){
261       case 3:
262         aCoordHelperPtr.reset(new TCoordHelper(aNodesIter,aXYZGetCoord,aXYZName));
263         break;
264       case 2:
265         if(anIsXDimension && anIsYDimension)
266           aCoordHelperPtr.reset(new TCoordHelper(aNodesIter,aXYGetCoord,aXYName));
267         if(anIsYDimension && anIsZDimension)
268           aCoordHelperPtr.reset(new TCoordHelper(aNodesIter,aYZGetCoord,aYZName));
269         if(anIsXDimension && anIsZDimension)
270           aCoordHelperPtr.reset(new TCoordHelper(aNodesIter,aXZGetCoord,aXZName));
271         break;
272       case 1:
273         if(anIsXDimension)
274           aCoordHelperPtr.reset(new TCoordHelper(aNodesIter,aXGetCoord,aXName));
275         if(anIsYDimension)
276           aCoordHelperPtr.reset(new TCoordHelper(aNodesIter,aYGetCoord,aYName));
277         if(anIsZDimension)
278           aCoordHelperPtr.reset(new TCoordHelper(aNodesIter,aZGetCoord,aZName));
279         break;
280       }
281     }
282
283     
284     PMeshInfo aMeshInfo = myMed->CrMeshInfo(aMeshDimension,aMeshName);
285     MESSAGE("Add - aMeshName : "<<aMeshName<<"; "<<aMeshInfo->GetName());
286     myMed->SetMeshInfo(aMeshInfo);
287
288     // Storing SMDS groups and sub-meshes
289     //-----------------------------------
290     int myNodesDefaultFamilyId = 0;
291     int myEdgesDefaultFamilyId = 0;
292     int myFacesDefaultFamilyId = 0;
293     int myVolumesDefaultFamilyId = 0;
294     if (myDoGroupOfNodes)
295       myNodesDefaultFamilyId = REST_NODES_FAMILY;
296     if (myDoGroupOfEdges)
297       myEdgesDefaultFamilyId = REST_EDGES_FAMILY;
298     if (myDoGroupOfFaces)
299       myFacesDefaultFamilyId = REST_FACES_FAMILY;
300     if (myDoGroupOfVolumes)
301       myVolumesDefaultFamilyId = REST_VOLUMES_FAMILY;
302
303     MESSAGE("Perform - aFamilyInfo");
304     map<const SMDS_MeshElement *, int> anElemFamMap;
305     list<DriverMED_FamilyPtr> aFamilies;
306     if (myAllSubMeshes) {
307       aFamilies = DriverMED_Family::MakeFamilies
308         (myMesh->SubMeshes(), myGroups,
309          myDoGroupOfNodes, myDoGroupOfEdges, myDoGroupOfFaces, myDoGroupOfVolumes);
310     } else {
311       aFamilies = DriverMED_Family::MakeFamilies
312         (mySubMeshes, myGroups,
313          myDoGroupOfNodes, myDoGroupOfEdges, myDoGroupOfFaces, myDoGroupOfVolumes);
314     }
315     list<DriverMED_FamilyPtr>::iterator aFamsIter = aFamilies.begin();
316
317     for (; aFamsIter != aFamilies.end(); aFamsIter++)
318     {
319       PFamilyInfo aFamilyInfo = (*aFamsIter)->GetFamilyInfo(myMed,aMeshInfo);
320       myMed->SetFamilyInfo(aFamilyInfo);
321       int aFamId = (*aFamsIter)->GetId();
322
323       const set<const SMDS_MeshElement *>& anElems = (*aFamsIter)->GetElements();
324       set<const SMDS_MeshElement *>::iterator anElemsIter = anElems.begin();
325       for (; anElemsIter != anElems.end(); anElemsIter++)
326       {
327         anElemFamMap[*anElemsIter] = aFamId;
328       }
329 //      delete (*aFamsIter);
330     }
331
332     // Storing SMDS nodes to the MED file for the MED mesh
333     //----------------------------------------------------
334 #ifdef _EDF_NODE_IDS_
335     typedef map<TInt,TInt> TNodeIdMap;
336     TNodeIdMap aNodeIdMap;
337 #endif
338     TInt aNbElems = myMesh->NbNodes();
339     MED::TIntVector anElemNums(aNbElems);
340     MED::TIntVector aFamilyNums(aNbElems);
341     MED::TFloatVector aCoordinates(aNbElems*aMeshDimension);
342     for(TInt iNode = 0, aStartId = 0; aCoordHelperPtr->Next(); iNode++, aStartId += aMeshDimension){
343       for(TInt iCoord = 0; iCoord < aMeshDimension; iCoord++){
344         aCoordinates[aStartId+iCoord] = aCoordHelperPtr->GetCoord(iCoord);
345       }
346       int aNodeID = aCoordHelperPtr->GetID();
347       anElemNums[iNode] = aNodeID;
348 #ifdef _EDF_NODE_IDS_
349       aNodeIdMap[aNodeID] = iNode+1;
350 #endif
351       const SMDS_MeshNode* aNode = aCoordHelperPtr->GetNode();
352       if (anElemFamMap.find(aNode) != anElemFamMap.end())
353         aFamilyNums[iNode] = anElemFamMap[aNode];
354       else
355         aFamilyNums[iNode] = myNodesDefaultFamilyId;
356     }
357
358     MED::TStringVector aCoordNames(aMeshDimension);
359     MED::TStringVector aCoordUnits(aMeshDimension);
360     for(TInt iCoord = 0; iCoord < aMeshDimension; iCoord++){
361       aCoordNames[iCoord] = aCoordHelperPtr->GetName(iCoord);
362       aCoordUnits[iCoord] = aCoordHelperPtr->GetUnit(iCoord);
363     }
364
365     const ERepere SMDS_COORDINATE_SYSTEM = eCART;
366
367     PNodeInfo aNodeInfo = myMed->CrNodeInfo(aMeshInfo,
368                                             aCoordinates,
369                                             eFULL_INTERLACE,
370                                             SMDS_COORDINATE_SYSTEM,
371                                             aCoordNames,
372                                             aCoordUnits,
373                                             aFamilyNums,
374                                             anElemNums);
375     MESSAGE("Perform - aNodeInfo->GetNbElem() = "<<aNbElems);
376     myMed->SetNodeInfo(aNodeInfo);
377
378
379     // Storing others SMDS elements to the MED file for the MED mesh
380     //--------------------------------------------------------------
381     EEntiteMaillage SMDS_MED_ENTITY = eMAILLE;
382     const EConnectivite SMDS_MED_CONNECTIVITY = eNOD;
383
384     // Storing SMDS Edges
385     if(TInt aNbElems = myMesh->NbEdges()){
386 #ifdef _ELEMENTS_BY_DIM_
387       SMDS_MED_ENTITY = eARETE;
388 #endif
389       SMDS_EdgeIteratorPtr anIter = myMesh->edgesIterator();
390       TInt aNbConnectivity = MED::GetNbNodes(eSEG2);
391       MED::TIntVector anElemNums(aNbElems);
392       MED::TIntVector aFamilyNums(aNbElems);
393       MED::TIntVector aConnectivity(aNbElems*aNbConnectivity);
394
395       for(TInt iElem = 0, iConn = 0; anIter->more(); iElem++, iConn+=aNbConnectivity){
396         const SMDS_MeshEdge* anElem = anIter->next();
397         SMDS_ElemIteratorPtr aNodesIter = anElem->nodesIterator();
398         for(TInt iNode = 0; iNode < aNbConnectivity && aNodesIter->more(); iNode++){
399           const SMDS_MeshElement* aNode = aNodesIter->next();
400 #ifdef _EDF_NODE_IDS_
401           aConnectivity[iConn+iNode] = aNodeIdMap[aNode->GetID()];
402 #else
403           aConnectivity[iConn+iNode] = aNode->GetID();
404 #endif
405         }
406         anElemNums[iElem] = anElem->GetID();
407
408         if (anElemFamMap.find(anElem) != anElemFamMap.end())
409           aFamilyNums[iElem] = anElemFamMap[anElem];
410         else
411           aFamilyNums[iElem] = myEdgesDefaultFamilyId;
412       }
413       
414       PCellInfo aCellInfo = myMed->CrCellInfo(aMeshInfo,
415                                               SMDS_MED_ENTITY,
416                                               eSEG2,
417                                               aConnectivity,
418                                               SMDS_MED_CONNECTIVITY,
419                                               aFamilyNums,
420                                               anElemNums);
421       myMed->SetCellInfo(aCellInfo);
422     }
423
424     // Storing SMDS Faces
425     if(TInt aNbElems = myMesh->NbFaces()){
426       SMDS_FaceIteratorPtr anIter = myMesh->facesIterator();
427 #ifdef _ELEMENTS_BY_DIM_
428       SMDS_MED_ENTITY = eFACE;
429 #endif
430       TInt aNbTriaConn = MED::GetNbNodes(eTRIA3);
431       MED::TIntVector anTriaElemNums; 
432       anTriaElemNums.reserve(aNbElems);
433       MED::TIntVector aTriaFamilyNums;
434       aTriaFamilyNums.reserve(aNbElems);
435       MED::TIntVector aTriaConn;
436       aTriaConn.reserve(aNbElems*aNbTriaConn);
437
438       TInt aNbQuadConn = MED::GetNbNodes(eQUAD4);
439       MED::TIntVector aQuadElemNums;
440       aQuadElemNums.reserve(aNbElems);
441       MED::TIntVector aQuadFamilyNums;
442       aQuadFamilyNums.reserve(aNbElems);
443       MED::TIntVector aQuadConn;
444       aQuadConn.reserve(aNbElems*aNbQuadConn);
445
446       MED::TIntVector aPolygoneElemNums;
447       aPolygoneElemNums.reserve(aNbElems);
448       MED::TIntVector aPolygoneInds;
449       aPolygoneInds.reserve(aNbElems + 1);
450       aPolygoneInds.push_back(1); // reference on the first element in the connectivities
451       MED::TIntVector aPolygoneFamilyNums;
452       aPolygoneFamilyNums.reserve(aNbElems);
453       MED::TIntVector aPolygoneConn;
454       aPolygoneConn.reserve(aNbElems*aNbQuadConn);
455
456       for(TInt iElem = 0; iElem < aNbElems && anIter->more(); iElem++){
457         const SMDS_MeshFace* anElem = anIter->next();
458         TInt aNbNodes = anElem->NbNodes();
459         SMDS_ElemIteratorPtr aNodesIter = anElem->nodesIterator();
460         TInt aNbConnectivity;
461         MED::TIntVector* anElemNums;
462         MED::TIntVector* aFamilyNums;
463         MED::TIntVector* aConnectivity;
464         if (anElem->IsPoly()) {
465           aNbConnectivity = aNbNodes;
466           anElemNums = &aPolygoneElemNums;
467           aFamilyNums = &aPolygoneFamilyNums;
468           aConnectivity = &aPolygoneConn;
469         } else {
470           switch(aNbNodes){
471           case 3:
472             aNbConnectivity = aNbTriaConn;
473             anElemNums = &anTriaElemNums;
474             aFamilyNums = &aTriaFamilyNums;
475             aConnectivity = &aTriaConn;
476             break;
477           case 4:
478             aNbConnectivity = aNbQuadConn;
479             anElemNums = &aQuadElemNums;
480             aFamilyNums = &aQuadFamilyNums;
481             aConnectivity = &aQuadConn;
482             break;
483           default:
484             break;
485           }
486         }
487         MED::TIntVector aVector(aNbNodes);
488         for(TInt iNode = 0; aNodesIter->more(); iNode++){
489           const SMDS_MeshElement* aNode = aNodesIter->next();
490 #ifdef _EDF_NODE_IDS_
491           aVector[iNode] = aNodeIdMap[aNode->GetID()];
492 #else
493           aVector[iNode] = aNode->GetID();
494 #endif
495         }
496
497         TInt aSize = aConnectivity->size();
498         aConnectivity->resize(aSize+aNbConnectivity);
499         // There is some differences between SMDS and MED in cells mapping
500         switch(aNbNodes){
501         case 4:
502           (*aConnectivity)[aSize+0] = aVector[0];
503           (*aConnectivity)[aSize+1] = aVector[1];
504           (*aConnectivity)[aSize+2] = aVector[3];  
505           (*aConnectivity)[aSize+3] = aVector[2];  
506         default:
507           for(TInt iNode = 0; iNode < aNbNodes; iNode++) 
508             (*aConnectivity)[aSize+iNode] = aVector[iNode];
509         }
510
511         if (anElem->IsPoly()) {
512           // fill indices for polygonal element
513           TInt aPrevPos = aPolygoneInds.back();
514           aPolygoneInds.push_back(aPrevPos + aNbNodes);
515         }
516
517         anElemNums->push_back(anElem->GetID());
518
519         if (anElemFamMap.find(anElem) != anElemFamMap.end())
520           aFamilyNums->push_back(anElemFamMap[anElem]);
521         else
522           aFamilyNums->push_back(myFacesDefaultFamilyId);
523       }
524       if(TInt aNbElems = anTriaElemNums.size()){
525         PCellInfo aCellInfo = myMed->CrCellInfo(aMeshInfo,
526                                                 SMDS_MED_ENTITY,
527                                                 eTRIA3,
528                                                 aTriaConn,
529                                                 SMDS_MED_CONNECTIVITY,
530                                                 aTriaFamilyNums,
531                                                 anTriaElemNums);
532         MESSAGE("Perform - anEntity = "<<SMDS_MED_ENTITY<<"; aGeom = "<<eTRIA3<<"; aNbElems = "<<aNbElems);
533         myMed->SetCellInfo(aCellInfo);
534       }
535       if(TInt aNbElems = aQuadElemNums.size()){
536         PCellInfo aCellInfo = myMed->CrCellInfo(aMeshInfo,
537                                                 SMDS_MED_ENTITY,
538                                                 eQUAD4,
539                                                 aQuadConn,
540                                                 SMDS_MED_CONNECTIVITY,
541                                                 aQuadFamilyNums,
542                                                 aQuadElemNums);
543         MESSAGE("Perform - anEntity = "<<SMDS_MED_ENTITY<<"; aGeom = "<<eQUAD4<<"; aNbElems = "<<aNbElems);
544         myMed->SetCellInfo(aCellInfo);
545       }
546       if(TInt aNbElems = aPolygoneElemNums.size()){
547         // add one element in connectivities,
548         // referenced by the last element in indices
549         aPolygoneConn.push_back(0);
550
551         PPolygoneInfo aCellInfo = myMed->CrPolygoneInfo(aMeshInfo,
552                                                         SMDS_MED_ENTITY,
553                                                         ePOLYGONE,
554                                                         aPolygoneConn,
555                                                         aPolygoneInds,
556                                                         SMDS_MED_CONNECTIVITY,
557                                                         aPolygoneFamilyNums,
558                                                         aPolygoneElemNums);
559         MESSAGE("Perform - anEntity = "<<SMDS_MED_ENTITY<<"; aGeom = "<<ePOLYGONE<<"; aNbElems = "<<aNbElems);
560         myMed->SetPolygoneInfo(aCellInfo);
561       }
562     }
563
564     // Storing SMDS Volumes
565     if(TInt aNbElems = myMesh->NbVolumes()){
566       SMDS_VolumeIteratorPtr anIter = myMesh->volumesIterator();
567 #ifdef _ELEMENTS_BY_DIM_
568       SMDS_MED_ENTITY = eMAILLE;
569 #endif
570       TInt aNbTetraConn = MED::GetNbNodes(eTETRA4);
571       MED::TIntVector anTetraElemNums; 
572       anTetraElemNums.reserve(aNbElems);
573       MED::TIntVector aTetraFamilyNums;
574       aTetraFamilyNums.reserve(aNbElems);
575       MED::TIntVector aTetraConn;
576       aTetraConn.reserve(aNbElems*aNbTetraConn);
577
578       TInt aNbPyraConn = MED::GetNbNodes(ePYRA5);
579       MED::TIntVector anPyraElemNums; 
580       anPyraElemNums.reserve(aNbElems);
581       MED::TIntVector aPyraFamilyNums;
582       aPyraFamilyNums.reserve(aNbElems);
583       MED::TIntVector aPyraConn;
584       aPyraConn.reserve(aNbElems*aNbPyraConn);
585
586       TInt aNbPentaConn = MED::GetNbNodes(ePENTA6);
587       MED::TIntVector anPentaElemNums; 
588       anPentaElemNums.reserve(aNbElems);
589       MED::TIntVector aPentaFamilyNums;
590       aPentaFamilyNums.reserve(aNbElems);
591       MED::TIntVector aPentaConn;
592       aPentaConn.reserve(aNbElems*aNbPentaConn);
593
594       TInt aNbHexaConn = MED::GetNbNodes(eHEXA8);
595       MED::TIntVector aHexaElemNums;
596       aHexaElemNums.reserve(aNbElems);
597       MED::TIntVector aHexaFamilyNums;
598       aHexaFamilyNums.reserve(aNbElems);
599       MED::TIntVector aHexaConn;
600       aHexaConn.reserve(aNbElems*aNbHexaConn);
601
602       MED::TIntVector aPolyedreElemNums;
603       aPolyedreElemNums.reserve(aNbElems);
604       MED::TIntVector aPolyedreInds;
605       aPolyedreInds.reserve(aNbElems + 1);
606       aPolyedreInds.push_back(1); // reference on the first element in the faces
607       MED::TIntVector aPolyedreFaces;
608       aPolyedreFaces.reserve(aNbElems + 1);
609       aPolyedreFaces.push_back(1); // reference on the first element in the connectivities
610       MED::TIntVector aPolyedreFamilyNums;
611       aPolyedreFamilyNums.reserve(aNbElems);
612       MED::TIntVector aPolyedreConn;
613       aPolyedreConn.reserve(aNbElems*aNbHexaConn);
614
615       for(TInt iElem = 0; iElem < aNbElems && anIter->more(); iElem++){
616         const SMDS_MeshVolume* anElem = anIter->next();
617
618         MED::TIntVector* anElemNums;
619         MED::TIntVector* aFamilyNums;
620
621         if (anElem->IsPoly()) {
622           const SMDS_PolyhedralVolumeOfNodes* aPolyedre =
623             (const SMDS_PolyhedralVolumeOfNodes*) anElem;
624           if (!aPolyedre) {
625             MESSAGE("Warning: bad volumic element");
626             continue;
627           }
628
629           anElemNums = &aPolyedreElemNums;
630           aFamilyNums = &aPolyedreFamilyNums;
631
632           TInt aNodeId, aNbFaces = aPolyedre->NbFaces();
633           for (int iface = 1; iface <= aNbFaces; iface++) {
634             int aNbFaceNodes = aPolyedre->NbFaceNodes(iface);
635             for (int inode = 1; inode <= aNbFaceNodes; inode++) {
636               aNodeId = aPolyedre->GetFaceNode(iface, inode)->GetID();
637 #ifdef _EDF_NODE_IDS_
638               aPolyedreConn.push_back(aNodeIdMap[aNodeId]);
639 #else
640               aPolyedreConn.push_back(aNodeId);
641 #endif
642             }
643             TInt aPrevPos = aPolyedreFaces.back();
644             aPolyedreFaces.push_back(aPrevPos + aNbFaceNodes);
645           }
646           TInt aPrevPos = aPolyedreInds.back();
647           aPolyedreInds.push_back(aPrevPos + aNbFaces);
648
649         } else {
650           TInt aNbNodes = anElem->NbNodes();
651           SMDS_ElemIteratorPtr aNodesIter = anElem->nodesIterator();
652           TInt aNbConnectivity;
653           MED::TIntVector* aConnectivity;
654           switch(aNbNodes){
655           case 4:
656             aNbConnectivity = aNbTetraConn;
657             anElemNums = &anTetraElemNums;
658             aFamilyNums = &aTetraFamilyNums;
659             aConnectivity = &aTetraConn;
660             break;
661           case 5:
662             aNbConnectivity = aNbPyraConn;
663             anElemNums = &anPyraElemNums;
664             aFamilyNums = &aPyraFamilyNums;
665             aConnectivity = &aPyraConn;
666             break;
667           case 6:
668             aNbConnectivity = aNbPentaConn;
669             anElemNums = &anPentaElemNums;
670             aFamilyNums = &aPentaFamilyNums;
671             aConnectivity = &aPentaConn;
672             break;
673           case 8:
674             aNbConnectivity = aNbHexaConn;
675             anElemNums = &aHexaElemNums;
676             aFamilyNums = &aHexaFamilyNums;
677             aConnectivity = &aHexaConn;
678           }
679
680           TInt aSize = aConnectivity->size();
681           aConnectivity->resize(aSize + aNbConnectivity);
682
683           MED::TIntVector aVector(aNbNodes);
684           for(TInt iNode = 0; aNodesIter->more(); iNode++){
685             const SMDS_MeshElement* aNode = aNodesIter->next();
686 #ifdef _EDF_NODE_IDS_
687             aVector[iNode] = aNodeIdMap[aNode->GetID()];
688 #else
689             aVector[iNode] = aNode->GetID();
690 #endif
691           }
692           // There is some difference between SMDS and MED in cells mapping
693           switch(aNbNodes){
694           case 5:
695             (*aConnectivity)[aSize+0] = aVector[0];
696             (*aConnectivity)[aSize+1] = aVector[3];
697             (*aConnectivity)[aSize+2] = aVector[2];  
698             (*aConnectivity)[aSize+3] = aVector[1];  
699             (*aConnectivity)[aSize+4] = aVector[4];  
700           default:
701             for(TInt iNode = 0; iNode < aNbNodes; iNode++) 
702               (*aConnectivity)[aSize+iNode] = aVector[iNode];
703           }
704         }
705
706         anElemNums->push_back(anElem->GetID());
707
708         if (anElemFamMap.find(anElem) != anElemFamMap.end())
709           aFamilyNums->push_back(anElemFamMap[anElem]);
710         else
711           aFamilyNums->push_back(myVolumesDefaultFamilyId);
712       }
713
714       if(TInt aNbElems = anTetraElemNums.size()){
715         PCellInfo aCellInfo = myMed->CrCellInfo(aMeshInfo,
716                                                 SMDS_MED_ENTITY,
717                                                 eTETRA4,
718                                                 aTetraConn,
719                                                 SMDS_MED_CONNECTIVITY,
720                                                 aTetraFamilyNums,
721                                                 anTetraElemNums);
722         MESSAGE("Perform - anEntity = "<<SMDS_MED_ENTITY<<"; aGeom = "<<eTETRA4<<"; aNbElems = "<<aNbElems);
723         myMed->SetCellInfo(aCellInfo);
724       }
725       if(TInt aNbElems = anPyraElemNums.size()){
726         PCellInfo aCellInfo = myMed->CrCellInfo(aMeshInfo,
727                                                 SMDS_MED_ENTITY,
728                                                 ePYRA5,
729                                                 aPyraConn,
730                                                 SMDS_MED_CONNECTIVITY,
731                                                 aPyraFamilyNums,
732                                                 anPyraElemNums);
733         MESSAGE("Perform - anEntity = "<<SMDS_MED_ENTITY<<"; aGeom = "<<ePYRA5<<"; aNbElems = "<<aNbElems);
734         myMed->SetCellInfo(aCellInfo);
735       }
736       if(TInt aNbElems = anPentaElemNums.size()){
737         PCellInfo aCellInfo = myMed->CrCellInfo(aMeshInfo,
738                                                 SMDS_MED_ENTITY,
739                                                 ePENTA6,
740                                                 aPentaConn,
741                                                 SMDS_MED_CONNECTIVITY,
742                                                 aPentaFamilyNums,
743                                                 anPentaElemNums);
744         MESSAGE("Perform - anEntity = "<<SMDS_MED_ENTITY<<"; aGeom = "<<ePENTA6<<"; aNbElems = "<<aNbElems);
745         myMed->SetCellInfo(aCellInfo);
746       }
747       if(TInt aNbElems = aHexaElemNums.size()){
748         PCellInfo aCellInfo = myMed->CrCellInfo(aMeshInfo,
749                                                 SMDS_MED_ENTITY,
750                                                 eHEXA8,
751                                                 aHexaConn,
752                                                 SMDS_MED_CONNECTIVITY,
753                                                 aHexaFamilyNums,
754                                                 aHexaElemNums);
755         MESSAGE("Perform - anEntity = "<<SMDS_MED_ENTITY<<"; aGeom = "<<eHEXA8<<"; aNbElems = "<<aNbElems);
756         myMed->SetCellInfo(aCellInfo);
757       }
758       if(TInt aNbElems = aPolyedreElemNums.size()){
759         // add one element in connectivities,
760         // referenced by the last element in faces
761         aPolyedreConn.push_back(0);
762
763         PPolyedreInfo aCellInfo = myMed->CrPolyedreInfo(aMeshInfo,
764                                                         SMDS_MED_ENTITY,
765                                                         ePOLYEDRE,
766                                                         aPolyedreInds,
767                                                         aPolyedreFaces,
768                                                         aPolyedreConn,
769                                                         SMDS_MED_CONNECTIVITY,
770                                                         aPolyedreFamilyNums,
771                                                         aPolyedreElemNums);
772         MESSAGE("Perform - anEntity = "<<SMDS_MED_ENTITY<<"; aGeom = "<<ePOLYEDRE<<"; aNbElems = "<<aNbElems);
773         myMed->SetPolyedreInfo(aCellInfo);
774       }
775     }
776   }catch(const std::exception& exc){
777     INFOS("Follow exception was cought:\n\t"<<exc.what());
778   }catch(...){
779     INFOS("Unknown exception was cought !!!");
780   }
781
782   myMeshId = -1;
783   myGroups.clear();
784   mySubMeshes.clear();
785   return aResult;
786 }