Salome HOME
PAL18696 SMESH : version of MED export
[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.salome-platform.org/ or email : webmaster.salome@opencascade.com
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 string DriverMED_W_SMESHDS_Mesh::GetVersionString(const MED::EVersion theVersion, int theNbDigits)
70 {
71   TInt majeur, mineur, release;
72   majeur =  mineur = release = 0;
73   if ( theVersion == eV2_1 )
74     MED::GetVersionRelease<eV2_1>(majeur, mineur, release);
75   else
76     MED::GetVersionRelease<eV2_2>(majeur, mineur, release);
77   ostringstream name;
78   if ( theNbDigits > 0 )
79     name << majeur;
80   if ( theNbDigits > 1 )
81     name << "." << mineur;
82   if ( theNbDigits > 2 )
83     name << "." << release;
84   return name.str();
85 }
86
87 void DriverMED_W_SMESHDS_Mesh::SetMeshName(const std::string& theMeshName)
88 {
89   myMeshName = theMeshName;
90 }
91
92 void DriverMED_W_SMESHDS_Mesh::AddGroup(SMESHDS_GroupBase* theGroup)
93 {
94   myGroups.push_back(theGroup);
95 }
96
97 void DriverMED_W_SMESHDS_Mesh::AddAllSubMeshes()
98 {
99   myAllSubMeshes = true;
100 }
101
102 void DriverMED_W_SMESHDS_Mesh::AddSubMesh(SMESHDS_SubMesh* theSubMesh, int theID)
103 {
104   mySubMeshes[theID] = theSubMesh;
105 }
106
107 void DriverMED_W_SMESHDS_Mesh::AddGroupOfNodes()
108 {
109   myDoGroupOfNodes = true;
110 }
111
112 void DriverMED_W_SMESHDS_Mesh::AddGroupOfEdges()
113 {
114   myDoGroupOfEdges = true;
115 }
116
117 void DriverMED_W_SMESHDS_Mesh::AddGroupOfFaces()
118 {
119   myDoGroupOfFaces = true;
120 }
121
122 void DriverMED_W_SMESHDS_Mesh::AddGroupOfVolumes()
123 {
124   myDoGroupOfVolumes = true;
125 }
126
127 namespace{
128   typedef double (SMDS_MeshNode::* TGetCoord)() const;
129   typedef const char* TName;
130   typedef const char* TUnit;
131
132   // name length in a mesh must be equal to 16 :
133   //         1234567890123456
134   TName M = "m               ";
135   TName X = "x               ";
136   TName Y = "y               ";
137   TName Z = "z               ";
138
139   TUnit aUnit[3] = {M,M,M};
140
141   // 3 dim
142   TGetCoord aXYZGetCoord[3] = {
143     &SMDS_MeshNode::X, 
144     &SMDS_MeshNode::Y, 
145     &SMDS_MeshNode::Z
146   };
147   TName aXYZName[3] = {X,Y,Z};
148   
149   // 2 dim
150   TGetCoord aXYGetCoord[2] = {
151     &SMDS_MeshNode::X, 
152     &SMDS_MeshNode::Y
153   };
154   TName aXYName[2] = {X,Y};
155
156   TGetCoord aYZGetCoord[2] = {
157     &SMDS_MeshNode::Y, 
158     &SMDS_MeshNode::Z
159   };
160   TName aYZName[2] = {Y,Z};
161
162   TGetCoord aXZGetCoord[2] = {
163     &SMDS_MeshNode::X, 
164     &SMDS_MeshNode::Z
165   };
166   TName aXZName[2] = {X,Z};
167
168   // 1 dim
169   TGetCoord aXGetCoord[1] = {
170     &SMDS_MeshNode::X
171   };
172   TName aXName[1] = {X};
173
174   TGetCoord aYGetCoord[1] = {
175     &SMDS_MeshNode::Y
176   };
177   TName aYName[1] = {Y};
178
179   TGetCoord aZGetCoord[1] = {
180     &SMDS_MeshNode::Z
181   };
182   TName aZName[1] = {Z};
183
184
185   class TCoordHelper{
186     SMDS_NodeIteratorPtr myNodeIter;
187     const SMDS_MeshNode* myCurrentNode;
188     TGetCoord* myGetCoord;
189     TName* myName;
190     TUnit* myUnit;
191   public:
192     TCoordHelper(const SMDS_NodeIteratorPtr& theNodeIter,
193                  TGetCoord* theGetCoord,
194                  TName* theName,
195                  TUnit* theUnit = aUnit):
196       myNodeIter(theNodeIter),
197       myGetCoord(theGetCoord),
198       myName(theName),
199       myUnit(theUnit)
200     {}
201     virtual ~TCoordHelper(){}
202     bool Next(){ 
203       return myNodeIter->more() && 
204         (myCurrentNode = myNodeIter->next());
205     }
206     const SMDS_MeshNode* GetNode(){
207       return myCurrentNode;
208     }
209     MED::TIntVector::value_type GetID(){
210       return myCurrentNode->GetID();
211     }
212     MED::TFloatVector::value_type GetCoord(TInt theCoodId){
213       return (myCurrentNode->*myGetCoord[theCoodId])();
214     }
215     MED::TStringVector::value_type GetName(TInt theDimId){
216       return myName[theDimId];
217     }
218     MED::TStringVector::value_type GetUnit(TInt theDimId){
219       return myUnit[theDimId];
220     }
221   };
222   typedef boost::shared_ptr<TCoordHelper> TCoordHelperPtr;
223   
224 }
225
226   
227 Driver_Mesh::Status DriverMED_W_SMESHDS_Mesh::Perform()
228 {
229   Status aResult = DRS_OK;
230   if (myMesh->hasConstructionEdges() || myMesh->hasConstructionFaces()) {
231     INFOS("SMDS_MESH with hasConstructionEdges() or hasConstructionFaces() do not supports!!!");
232     return DRS_FAIL;
233   }
234   try{
235     MESSAGE("Perform - myFile : "<<myFile);
236
237     // Creating the MED mesh for corresponding SMDS structure
238     //-------------------------------------------------------
239     string aMeshName;
240     if (myMeshId != -1) {
241       ostringstream aMeshNameStr;
242       aMeshNameStr<<myMeshId;
243       aMeshName = aMeshNameStr.str();
244     } else {
245       aMeshName = myMeshName;
246     }
247
248     // Mesh dimension definition
249     TInt aMeshDimension;
250     TCoordHelperPtr aCoordHelperPtr;
251     {  
252       bool anIsXDimension = false;
253       bool anIsYDimension = false;
254       bool anIsZDimension = false;
255       {
256         SMDS_NodeIteratorPtr aNodesIter = myMesh->nodesIterator();
257         double aBounds[6];
258         if(aNodesIter->more()){
259           const SMDS_MeshNode* aNode = aNodesIter->next();
260           aBounds[0] = aBounds[1] = aNode->X();
261           aBounds[2] = aBounds[3] = aNode->Y();
262           aBounds[4] = aBounds[5] = aNode->Z();
263         }
264         while(aNodesIter->more()){
265           const SMDS_MeshNode* aNode = aNodesIter->next();
266           aBounds[0] = min(aBounds[0],aNode->X());
267           aBounds[1] = max(aBounds[1],aNode->X());
268           
269           aBounds[2] = min(aBounds[2],aNode->Y());
270           aBounds[3] = max(aBounds[3],aNode->Y());
271           
272           aBounds[4] = min(aBounds[4],aNode->Z());
273           aBounds[5] = max(aBounds[5],aNode->Z());
274         }
275
276         double EPS = 1.0E-7;
277         anIsXDimension = (aBounds[1] - aBounds[0]) + abs(aBounds[1]) + abs(aBounds[0]) > EPS;
278         anIsYDimension = (aBounds[3] - aBounds[2]) + abs(aBounds[3]) + abs(aBounds[2]) > EPS;
279         anIsZDimension = (aBounds[5] - aBounds[4]) + abs(aBounds[5]) + abs(aBounds[4]) > EPS;
280         aMeshDimension = anIsXDimension + anIsYDimension + anIsZDimension;
281         if(!aMeshDimension)
282           aMeshDimension = 3;
283         // PAL16857(SMESH not conform to the MED convention):
284         if ( aMeshDimension == 2 && anIsZDimension ) // 2D only if mesh is in XOY plane
285           aMeshDimension = 3;
286       }
287
288       SMDS_NodeIteratorPtr aNodesIter = myMesh->nodesIterator();
289       switch(aMeshDimension){
290       case 3:
291         aCoordHelperPtr.reset(new TCoordHelper(aNodesIter,aXYZGetCoord,aXYZName));
292         break;
293       case 2:
294         if(anIsXDimension && anIsYDimension)
295           aCoordHelperPtr.reset(new TCoordHelper(aNodesIter,aXYGetCoord,aXYName));
296         if(anIsYDimension && anIsZDimension)
297           aCoordHelperPtr.reset(new TCoordHelper(aNodesIter,aYZGetCoord,aYZName));
298         if(anIsXDimension && anIsZDimension)
299           aCoordHelperPtr.reset(new TCoordHelper(aNodesIter,aXZGetCoord,aXZName));
300         break;
301       case 1:
302         if(anIsXDimension)
303           aCoordHelperPtr.reset(new TCoordHelper(aNodesIter,aXGetCoord,aXName));
304         if(anIsYDimension)
305           aCoordHelperPtr.reset(new TCoordHelper(aNodesIter,aYGetCoord,aYName));
306         if(anIsZDimension)
307           aCoordHelperPtr.reset(new TCoordHelper(aNodesIter,aZGetCoord,aZName));
308         break;
309       }
310     }
311
312     
313     PMeshInfo aMeshInfo = myMed->CrMeshInfo(aMeshDimension,aMeshName);
314     MESSAGE("Add - aMeshName : "<<aMeshName<<"; "<<aMeshInfo->GetName());
315     myMed->SetMeshInfo(aMeshInfo);
316
317     // Storing SMDS groups and sub-meshes
318     //-----------------------------------
319     int myNodesDefaultFamilyId   = 0;
320     int myEdgesDefaultFamilyId   = 0;
321     int myFacesDefaultFamilyId   = 0;
322     int myVolumesDefaultFamilyId = 0;
323     int nbNodes   = myMesh->NbNodes();
324     int nbEdges   = myMesh->NbEdges();
325     int nbFaces   = myMesh->NbFaces();
326     int nbVolumes = myMesh->NbVolumes();
327     if (myDoGroupOfNodes && nbNodes)
328       myNodesDefaultFamilyId = REST_NODES_FAMILY;
329     if (myDoGroupOfEdges && nbEdges)
330       myEdgesDefaultFamilyId = REST_EDGES_FAMILY;
331     if (myDoGroupOfFaces && nbFaces)
332       myFacesDefaultFamilyId = REST_FACES_FAMILY;
333     if (myDoGroupOfVolumes && nbVolumes)
334       myVolumesDefaultFamilyId = REST_VOLUMES_FAMILY;
335
336     MESSAGE("Perform - aFamilyInfo");
337     map<const SMDS_MeshElement *, int> anElemFamMap;
338     list<DriverMED_FamilyPtr> aFamilies;
339     if (myAllSubMeshes) {
340       aFamilies = DriverMED_Family::MakeFamilies
341         (myMesh->SubMeshes(), myGroups,
342          myDoGroupOfNodes   && nbNodes,
343          myDoGroupOfEdges   && nbEdges,
344          myDoGroupOfFaces   && nbFaces,
345          myDoGroupOfVolumes && nbVolumes);
346     } else {
347       aFamilies = DriverMED_Family::MakeFamilies
348         (mySubMeshes, myGroups,
349          myDoGroupOfNodes   && nbNodes,
350          myDoGroupOfEdges   && nbEdges,
351          myDoGroupOfFaces   && nbFaces,
352          myDoGroupOfVolumes && nbVolumes);
353     }
354     list<DriverMED_FamilyPtr>::iterator aFamsIter = aFamilies.begin();
355
356     for (; aFamsIter != aFamilies.end(); aFamsIter++)
357     {
358       PFamilyInfo aFamilyInfo = (*aFamsIter)->GetFamilyInfo(myMed,aMeshInfo);
359       myMed->SetFamilyInfo(aFamilyInfo);
360       int aFamId = (*aFamsIter)->GetId();
361
362       const set<const SMDS_MeshElement *>& anElems = (*aFamsIter)->GetElements();
363       set<const SMDS_MeshElement *>::const_iterator anElemsIter = anElems.begin();
364       for (; anElemsIter != anElems.end(); anElemsIter++)
365       {
366         anElemFamMap[*anElemsIter] = aFamId;
367       }
368     }
369
370     // Storing SMDS nodes to the MED file for the MED mesh
371     //----------------------------------------------------
372 #ifdef _EDF_NODE_IDS_
373     typedef map<TInt,TInt> TNodeIdMap;
374     TNodeIdMap aNodeIdMap;
375 #endif
376     TInt aNbElems = myMesh->NbNodes();
377     MED::TIntVector anElemNums(aNbElems);
378     MED::TIntVector aFamilyNums(aNbElems);
379     MED::TFloatVector aCoordinates(aNbElems*aMeshDimension);
380     for(TInt iNode = 0, aStartId = 0; aCoordHelperPtr->Next(); iNode++, aStartId += aMeshDimension){
381       for(TInt iCoord = 0; iCoord < aMeshDimension; iCoord++){
382         aCoordinates[aStartId+iCoord] = aCoordHelperPtr->GetCoord(iCoord);
383       }
384       int aNodeID = aCoordHelperPtr->GetID();
385       anElemNums[iNode] = aNodeID;
386 #ifdef _EDF_NODE_IDS_
387       aNodeIdMap[aNodeID] = iNode+1;
388 #endif
389       const SMDS_MeshNode* aNode = aCoordHelperPtr->GetNode();
390       if (anElemFamMap.find(aNode) != anElemFamMap.end())
391         aFamilyNums[iNode] = anElemFamMap[aNode];
392       else
393         aFamilyNums[iNode] = myNodesDefaultFamilyId;
394     }
395
396     MED::TStringVector aCoordNames(aMeshDimension);
397     MED::TStringVector aCoordUnits(aMeshDimension);
398     for(TInt iCoord = 0; iCoord < aMeshDimension; iCoord++){
399       aCoordNames[iCoord] = aCoordHelperPtr->GetName(iCoord);
400       aCoordUnits[iCoord] = aCoordHelperPtr->GetUnit(iCoord);
401     }
402
403     const ERepere SMDS_COORDINATE_SYSTEM = eCART;
404
405     PNodeInfo aNodeInfo = myMed->CrNodeInfo(aMeshInfo,
406                                             aCoordinates,
407                                             eFULL_INTERLACE,
408                                             SMDS_COORDINATE_SYSTEM,
409                                             aCoordNames,
410                                             aCoordUnits,
411                                             aFamilyNums,
412                                             anElemNums);
413     MESSAGE("Perform - aNodeInfo->GetNbElem() = "<<aNbElems);
414     myMed->SetNodeInfo(aNodeInfo);
415
416
417     // Storing others SMDS elements to the MED file for the MED mesh
418     //--------------------------------------------------------------
419     EEntiteMaillage SMDS_MED_ENTITY = eMAILLE;
420     const EConnectivite SMDS_MED_CONNECTIVITY = eNOD;
421
422     // Storing SMDS Edges
423     if(TInt aNbElems = myMesh->NbEdges()){
424 #ifdef _ELEMENTS_BY_DIM_
425       SMDS_MED_ENTITY = eARETE;
426 #endif
427       // count edges of diff types
428       int aNbSeg3 = 0, aNbSeg2 = 0;
429       SMDS_EdgeIteratorPtr anIter = myMesh->edgesIterator();
430       while ( anIter->more() )
431         if ( anIter->next()->NbNodes() == 3 )
432           ++aNbSeg3;
433       aNbSeg2 = aNbElems - aNbSeg3;
434
435       TInt aNbSeg2Conn = MED::GetNbNodes(eSEG2);
436       MED::TIntVector aSeg2ElemNums, aSeg2FamilyNums, aSeg2Conn;
437       aSeg2ElemNums  .reserve( aNbSeg2 );
438       aSeg2FamilyNums.reserve( aNbSeg2 );
439       aSeg2Conn      .reserve( aNbSeg2*aNbSeg2Conn );
440
441       TInt aNbSeg3Conn = MED::GetNbNodes(eSEG3);
442       MED::TIntVector aSeg3ElemNums, aSeg3FamilyNums, aSeg3Conn;
443       aSeg3ElemNums  .reserve( aNbSeg3 );
444       aSeg3FamilyNums.reserve( aNbSeg3 );
445       aSeg3Conn      .reserve( aNbSeg3*aNbSeg3Conn );
446
447       anIter = myMesh->edgesIterator();
448       while ( anIter->more() ) {
449         const SMDS_MeshEdge* anElem = anIter->next();
450         TInt aNbNodes = anElem->NbNodes();
451
452         TInt aNbConnectivity;
453         MED::TIntVector* anElemNums;
454         MED::TIntVector* aFamilyNums;
455         MED::TIntVector* aConnectivity;
456         switch(aNbNodes){
457         case 2:
458           aNbConnectivity = aNbSeg2Conn;
459           anElemNums      = &aSeg2ElemNums;
460           aFamilyNums     = &aSeg2FamilyNums;
461           aConnectivity   = &aSeg2Conn;
462           break;
463         case 3:
464           aNbConnectivity = aNbSeg3Conn;
465           anElemNums      = &aSeg3ElemNums;
466           aFamilyNums     = &aSeg3FamilyNums;
467           aConnectivity   = &aSeg3Conn;
468           break;
469         default:
470           break;
471         }
472
473         for(TInt iNode = 0; iNode < aNbNodes; iNode++) {
474           const SMDS_MeshElement* aNode = anElem->GetNode( iNode );
475 #ifdef _EDF_NODE_IDS_
476           aConnectivity->push_back( aNodeIdMap[aNode->GetID()] );
477 #else
478           aConnectivity->push_back( aNode->GetID() );
479 #endif
480         }
481
482         anElemNums->push_back(anElem->GetID());
483
484         map<const SMDS_MeshElement*,int>::iterator edge_fam = anElemFamMap.find( anElem );
485         if ( edge_fam != anElemFamMap.end() )
486           aFamilyNums->push_back( edge_fam->second );
487         else
488           aFamilyNums->push_back( myEdgesDefaultFamilyId );
489       }
490       
491       if ( aNbSeg2 ) {
492         PCellInfo aCellInfo = myMed->CrCellInfo(aMeshInfo,
493                                                 SMDS_MED_ENTITY,
494                                                 eSEG2,
495                                                 aSeg2Conn,
496                                                 SMDS_MED_CONNECTIVITY,
497                                                 aSeg2FamilyNums,
498                                                 aSeg2ElemNums);
499         myMed->SetCellInfo(aCellInfo);
500       }
501       if ( aNbSeg3 ) {
502         PCellInfo aCellInfo = myMed->CrCellInfo(aMeshInfo,
503                                                 SMDS_MED_ENTITY,
504                                                 eSEG3,
505                                                 aSeg3Conn,
506                                                 SMDS_MED_CONNECTIVITY,
507                                                 aSeg3FamilyNums,
508                                                 aSeg3ElemNums);
509         myMed->SetCellInfo(aCellInfo);
510       }
511     }
512
513     // Storing SMDS Faces
514     if(TInt aNbElems = myMesh->NbFaces()){
515       SMDS_FaceIteratorPtr anIter = myMesh->facesIterator();
516 #ifdef _ELEMENTS_BY_DIM_
517       SMDS_MED_ENTITY = eFACE;
518 #endif
519       TInt aNbTriaConn = MED::GetNbNodes(eTRIA3);
520       MED::TIntVector anTriaElemNums; 
521       anTriaElemNums.reserve(aNbElems);
522       MED::TIntVector aTriaFamilyNums;
523       aTriaFamilyNums.reserve(aNbElems);
524       MED::TIntVector aTriaConn;
525       aTriaConn.reserve(aNbElems*aNbTriaConn);
526
527       TInt aNbTria6Conn = MED::GetNbNodes(eTRIA6);
528       MED::TIntVector anTria6ElemNums; 
529       anTria6ElemNums.reserve(aNbElems);
530       MED::TIntVector aTria6FamilyNums;
531       aTria6FamilyNums.reserve(aNbElems);
532       MED::TIntVector aTria6Conn;
533       aTria6Conn.reserve(aNbElems*aNbTria6Conn);
534
535       TInt aNbQuadConn = MED::GetNbNodes(eQUAD4);
536       MED::TIntVector aQuadElemNums;
537       aQuadElemNums.reserve(aNbElems);
538       MED::TIntVector aQuadFamilyNums;
539       aQuadFamilyNums.reserve(aNbElems);
540       MED::TIntVector aQuadConn;
541       aQuadConn.reserve(aNbElems*aNbQuadConn);
542
543       TInt aNbQuad8Conn = MED::GetNbNodes(eQUAD8);
544       MED::TIntVector aQuad8ElemNums;
545       aQuad8ElemNums.reserve(aNbElems);
546       MED::TIntVector aQuad8FamilyNums;
547       aQuad8FamilyNums.reserve(aNbElems);
548       MED::TIntVector aQuad8Conn;
549       aQuad8Conn.reserve(aNbElems*aNbQuad8Conn);
550
551       MED::TIntVector aPolygoneElemNums;
552       aPolygoneElemNums.reserve(aNbElems);
553       MED::TIntVector aPolygoneInds;
554       aPolygoneInds.reserve(aNbElems + 1);
555       aPolygoneInds.push_back(1); // reference on the first element in the connectivities
556       MED::TIntVector aPolygoneFamilyNums;
557       aPolygoneFamilyNums.reserve(aNbElems);
558       MED::TIntVector aPolygoneConn;
559       aPolygoneConn.reserve(aNbElems*aNbQuadConn);
560
561       for(TInt iElem = 0; iElem < aNbElems && anIter->more(); iElem++){
562         const SMDS_MeshFace* anElem = anIter->next();
563         TInt aNbNodes = anElem->NbNodes();
564         SMDS_ElemIteratorPtr aNodesIter = anElem->nodesIterator();
565         TInt aNbConnectivity;
566         MED::TIntVector* anElemNums;
567         MED::TIntVector* aFamilyNums;
568         MED::TIntVector* aConnectivity;
569         if (anElem->IsPoly()) {
570           aNbConnectivity = aNbNodes;
571           anElemNums = &aPolygoneElemNums;
572           aFamilyNums = &aPolygoneFamilyNums;
573           aConnectivity = &aPolygoneConn;
574         }
575         else {
576           switch(aNbNodes){
577           case 3:
578             aNbConnectivity = aNbTriaConn;
579             anElemNums = &anTriaElemNums;
580             aFamilyNums = &aTriaFamilyNums;
581             aConnectivity = &aTriaConn;
582             break;
583           case 4:
584             aNbConnectivity = aNbQuadConn;
585             anElemNums = &aQuadElemNums;
586             aFamilyNums = &aQuadFamilyNums;
587             aConnectivity = &aQuadConn;
588             break;
589           case 6:
590             aNbConnectivity = aNbTria6Conn;
591             anElemNums = &anTria6ElemNums;
592             aFamilyNums = &aTria6FamilyNums;
593             aConnectivity = &aTria6Conn;
594             break;
595           case 8:
596             aNbConnectivity = aNbQuad8Conn;
597             anElemNums = &aQuad8ElemNums;
598             aFamilyNums = &aQuad8FamilyNums;
599             aConnectivity = &aQuad8Conn;
600             break;
601           default:
602             break;
603           }
604         }
605         MED::TIntVector aVector(aNbNodes);
606         for(TInt iNode = 0; aNodesIter->more(); iNode++){
607           const SMDS_MeshElement* aNode = aNodesIter->next();
608 #ifdef _EDF_NODE_IDS_
609           aVector[iNode] = aNodeIdMap[aNode->GetID()];
610 #else
611           aVector[iNode] = aNode->GetID();
612 #endif
613         }
614
615         TInt aSize = aConnectivity->size();
616         aConnectivity->resize(aSize+aNbConnectivity);
617         // There is some differences between SMDS and MED in cells mapping
618         switch(aNbNodes){
619         case 4:
620           (*aConnectivity)[aSize+0] = aVector[0];
621           (*aConnectivity)[aSize+1] = aVector[1];
622           (*aConnectivity)[aSize+2] = aVector[3];  
623           (*aConnectivity)[aSize+3] = aVector[2];  
624         default:
625           for(TInt iNode = 0; iNode < aNbNodes; iNode++) 
626             (*aConnectivity)[aSize+iNode] = aVector[iNode];
627         }
628
629         if (anElem->IsPoly()) {
630           // fill indices for polygonal element
631           TInt aPrevPos = aPolygoneInds.back();
632           aPolygoneInds.push_back(aPrevPos + aNbNodes);
633         }
634
635         anElemNums->push_back(anElem->GetID());
636
637         if (anElemFamMap.find(anElem) != anElemFamMap.end())
638           aFamilyNums->push_back(anElemFamMap[anElem]);
639         else
640           aFamilyNums->push_back(myFacesDefaultFamilyId);
641       }
642       if(TInt aNbElems = anTriaElemNums.size()){
643         PCellInfo aCellInfo = myMed->CrCellInfo(aMeshInfo,
644                                                 SMDS_MED_ENTITY,
645                                                 eTRIA3,
646                                                 aTriaConn,
647                                                 SMDS_MED_CONNECTIVITY,
648                                                 aTriaFamilyNums,
649                                                 anTriaElemNums);
650         MESSAGE("Perform - anEntity = "<<SMDS_MED_ENTITY<<"; aGeom = "<<eTRIA3<<"; aNbElems = "<<aNbElems);
651         myMed->SetCellInfo(aCellInfo);
652       }
653       if(TInt aNbElems = aQuadElemNums.size()){
654         PCellInfo aCellInfo = myMed->CrCellInfo(aMeshInfo,
655                                                 SMDS_MED_ENTITY,
656                                                 eQUAD4,
657                                                 aQuadConn,
658                                                 SMDS_MED_CONNECTIVITY,
659                                                 aQuadFamilyNums,
660                                                 aQuadElemNums);
661         MESSAGE("Perform - anEntity = "<<SMDS_MED_ENTITY<<"; aGeom = "<<eQUAD4<<"; aNbElems = "<<aNbElems);
662         myMed->SetCellInfo(aCellInfo);
663       }
664       if(TInt aNbElems = anTria6ElemNums.size()){
665         PCellInfo aCellInfo = myMed->CrCellInfo(aMeshInfo,
666                                                 SMDS_MED_ENTITY,
667                                                 eTRIA6,
668                                                 aTria6Conn,
669                                                 SMDS_MED_CONNECTIVITY,
670                                                 aTria6FamilyNums,
671                                                 anTria6ElemNums);
672         MESSAGE("Perform - anEntity = "<<SMDS_MED_ENTITY<<"; aGeom = "<<eTRIA6<<"; aNbElems = "<<aNbElems);
673         myMed->SetCellInfo(aCellInfo);
674       }
675       if(TInt aNbElems = aQuad8ElemNums.size()){
676         PCellInfo aCellInfo = myMed->CrCellInfo(aMeshInfo,
677                                                 SMDS_MED_ENTITY,
678                                                 eQUAD8,
679                                                 aQuad8Conn,
680                                                 SMDS_MED_CONNECTIVITY,
681                                                 aQuad8FamilyNums,
682                                                 aQuad8ElemNums);
683         MESSAGE("Perform - anEntity = "<<SMDS_MED_ENTITY<<"; aGeom = "<<eQUAD8<<"; aNbElems = "<<aNbElems);
684         myMed->SetCellInfo(aCellInfo);
685       }
686       if(TInt aNbElems = aPolygoneElemNums.size()){
687         // add one element in connectivities,
688         // referenced by the last element in indices
689         aPolygoneConn.push_back(0);
690
691         PPolygoneInfo aCellInfo = myMed->CrPolygoneInfo(aMeshInfo,
692                                                         SMDS_MED_ENTITY,
693                                                         ePOLYGONE,
694                                                         aPolygoneInds,
695                                                         aPolygoneConn,
696                                                         SMDS_MED_CONNECTIVITY,
697                                                         aPolygoneFamilyNums,
698                                                         aPolygoneElemNums);
699         MESSAGE("Perform - anEntity = "<<SMDS_MED_ENTITY<<"; aGeom = "<<ePOLYGONE<<"; aNbElems = "<<aNbElems);
700         myMed->SetPolygoneInfo(aCellInfo);
701       }
702     }
703
704     // Storing SMDS Volumes
705     if(TInt aNbElems = myMesh->NbVolumes()){
706       SMDS_VolumeIteratorPtr anIter = myMesh->volumesIterator();
707 #ifdef _ELEMENTS_BY_DIM_
708       SMDS_MED_ENTITY = eMAILLE;
709 #endif
710       TInt aNbTetraConn = MED::GetNbNodes(eTETRA4);
711       MED::TIntVector anTetraElemNums; 
712       anTetraElemNums.reserve(aNbElems);
713       MED::TIntVector aTetraFamilyNums;
714       aTetraFamilyNums.reserve(aNbElems);
715       MED::TIntVector aTetraConn;
716       aTetraConn.reserve(aNbElems*aNbTetraConn);
717
718       TInt aNbPyraConn = MED::GetNbNodes(ePYRA5);
719       MED::TIntVector anPyraElemNums; 
720       anPyraElemNums.reserve(aNbElems);
721       MED::TIntVector aPyraFamilyNums;
722       aPyraFamilyNums.reserve(aNbElems);
723       MED::TIntVector aPyraConn;
724       aPyraConn.reserve(aNbElems*aNbPyraConn);
725
726       TInt aNbPentaConn = MED::GetNbNodes(ePENTA6);
727       MED::TIntVector anPentaElemNums; 
728       anPentaElemNums.reserve(aNbElems);
729       MED::TIntVector aPentaFamilyNums;
730       aPentaFamilyNums.reserve(aNbElems);
731       MED::TIntVector aPentaConn;
732       aPentaConn.reserve(aNbElems*aNbPentaConn);
733
734       TInt aNbHexaConn = MED::GetNbNodes(eHEXA8);
735       MED::TIntVector aHexaElemNums;
736       aHexaElemNums.reserve(aNbElems);
737       MED::TIntVector aHexaFamilyNums;
738       aHexaFamilyNums.reserve(aNbElems);
739       MED::TIntVector aHexaConn;
740       aHexaConn.reserve(aNbElems*aNbHexaConn);
741
742       TInt aNbTetra10Conn = MED::GetNbNodes(eTETRA10);
743       MED::TIntVector anTetra10ElemNums; 
744       anTetra10ElemNums.reserve(aNbElems);
745       MED::TIntVector aTetra10FamilyNums;
746       aTetra10FamilyNums.reserve(aNbElems);
747       MED::TIntVector aTetra10Conn;
748       aTetra10Conn.reserve(aNbElems*aNbTetra10Conn);
749
750       TInt aNbPyra13Conn = MED::GetNbNodes(ePYRA13);
751       MED::TIntVector anPyra13ElemNums; 
752       anPyra13ElemNums.reserve(aNbElems);
753       MED::TIntVector aPyra13FamilyNums;
754       aPyra13FamilyNums.reserve(aNbElems);
755       MED::TIntVector aPyra13Conn;
756       aPyra13Conn.reserve(aNbElems*aNbPyra13Conn);
757
758       TInt aNbPenta15Conn = MED::GetNbNodes(ePENTA15);
759       MED::TIntVector anPenta15ElemNums; 
760       anPenta15ElemNums.reserve(aNbElems);
761       MED::TIntVector aPenta15FamilyNums;
762       aPenta15FamilyNums.reserve(aNbElems);
763       MED::TIntVector aPenta15Conn;
764       aPenta15Conn.reserve(aNbElems*aNbPenta15Conn);
765
766       TInt aNbHexa20Conn = MED::GetNbNodes(eHEXA20);
767       MED::TIntVector aHexa20ElemNums;
768       aHexa20ElemNums.reserve(aNbElems);
769       MED::TIntVector aHexa20FamilyNums;
770       aHexa20FamilyNums.reserve(aNbElems);
771       MED::TIntVector aHexa20Conn;
772       aHexa20Conn.reserve(aNbElems*aNbHexa20Conn);
773
774       MED::TIntVector aPolyedreElemNums;
775       aPolyedreElemNums.reserve(aNbElems);
776       MED::TIntVector aPolyedreInds;
777       aPolyedreInds.reserve(aNbElems + 1);
778       aPolyedreInds.push_back(1); // reference on the first element in the faces
779       MED::TIntVector aPolyedreFaces;
780       aPolyedreFaces.reserve(aNbElems + 1);
781       aPolyedreFaces.push_back(1); // reference on the first element in the connectivities
782       MED::TIntVector aPolyedreFamilyNums;
783       aPolyedreFamilyNums.reserve(aNbElems);
784       MED::TIntVector aPolyedreConn;
785       aPolyedreConn.reserve(aNbElems*aNbHexaConn);
786
787       for(TInt iElem = 0; iElem < aNbElems && anIter->more(); iElem++){
788         const SMDS_MeshVolume* anElem = anIter->next();
789
790         MED::TIntVector* anElemNums;
791         MED::TIntVector* aFamilyNums;
792
793         if (anElem->IsPoly()) {
794           const SMDS_PolyhedralVolumeOfNodes* aPolyedre =
795             (const SMDS_PolyhedralVolumeOfNodes*) anElem;
796           if (!aPolyedre) {
797             MESSAGE("Warning: bad volumic element");
798             continue;
799           }
800
801           anElemNums = &aPolyedreElemNums;
802           aFamilyNums = &aPolyedreFamilyNums;
803
804           TInt aNodeId, aNbFaces = aPolyedre->NbFaces();
805           for (int iface = 1; iface <= aNbFaces; iface++) {
806             int aNbFaceNodes = aPolyedre->NbFaceNodes(iface);
807             for (int inode = 1; inode <= aNbFaceNodes; inode++) {
808               aNodeId = aPolyedre->GetFaceNode(iface, inode)->GetID();
809 #ifdef _EDF_NODE_IDS_
810               aPolyedreConn.push_back(aNodeIdMap[aNodeId]);
811 #else
812               aPolyedreConn.push_back(aNodeId);
813 #endif
814             }
815             TInt aPrevPos = aPolyedreFaces.back();
816             aPolyedreFaces.push_back(aPrevPos + aNbFaceNodes);
817           }
818           TInt aPrevPos = aPolyedreInds.back();
819           aPolyedreInds.push_back(aPrevPos + aNbFaces);
820
821         }
822         else {
823           TInt aNbNodes = anElem->NbNodes();
824           SMDS_ElemIteratorPtr aNodesIter = anElem->nodesIterator();
825           TInt aNbConnectivity;
826           MED::TIntVector* aConnectivity;
827           switch(aNbNodes){
828           case 4:
829             aNbConnectivity = aNbTetraConn;
830             anElemNums = &anTetraElemNums;
831             aFamilyNums = &aTetraFamilyNums;
832             aConnectivity = &aTetraConn;
833             break;
834           case 5:
835             aNbConnectivity = aNbPyraConn;
836             anElemNums = &anPyraElemNums;
837             aFamilyNums = &aPyraFamilyNums;
838             aConnectivity = &aPyraConn;
839             break;
840           case 6:
841             aNbConnectivity = aNbPentaConn;
842             anElemNums = &anPentaElemNums;
843             aFamilyNums = &aPentaFamilyNums;
844             aConnectivity = &aPentaConn;
845             break;
846           case 8:
847             aNbConnectivity = aNbHexaConn;
848             anElemNums = &aHexaElemNums;
849             aFamilyNums = &aHexaFamilyNums;
850             aConnectivity = &aHexaConn;
851             break;
852           case 10:
853             aNbConnectivity = aNbTetra10Conn;
854             anElemNums = &anTetra10ElemNums;
855             aFamilyNums = &aTetra10FamilyNums;
856             aConnectivity = &aTetra10Conn;
857             break;
858           case 13:
859             aNbConnectivity = aNbPyra13Conn;
860             anElemNums = &anPyra13ElemNums;
861             aFamilyNums = &aPyra13FamilyNums;
862             aConnectivity = &aPyra13Conn;
863             break;
864           case 15:
865             aNbConnectivity = aNbPenta15Conn;
866             anElemNums = &anPenta15ElemNums;
867             aFamilyNums = &aPenta15FamilyNums;
868             aConnectivity = &aPenta15Conn;
869             break;
870           case 20:
871             aNbConnectivity = aNbHexa20Conn;
872             anElemNums = &aHexa20ElemNums;
873             aFamilyNums = &aHexa20FamilyNums;
874             aConnectivity = &aHexa20Conn;
875           }
876
877           TInt aSize = aConnectivity->size();
878           aConnectivity->resize(aSize + aNbConnectivity);
879
880           MED::TIntVector aVector(aNbNodes);
881           for(TInt iNode = 0; aNodesIter->more(); iNode++){
882             const SMDS_MeshElement* aNode = aNodesIter->next();
883 #ifdef _EDF_NODE_IDS_
884             aVector[iNode] = aNodeIdMap[aNode->GetID()];
885 #else
886             aVector[iNode] = aNode->GetID();
887 #endif
888           }
889           // There is some difference between SMDS and MED in cells mapping
890           switch(aNbNodes){
891           case 5:
892             (*aConnectivity)[aSize+0] = aVector[0];
893             (*aConnectivity)[aSize+1] = aVector[3];
894             (*aConnectivity)[aSize+2] = aVector[2];  
895             (*aConnectivity)[aSize+3] = aVector[1];  
896             (*aConnectivity)[aSize+4] = aVector[4];  
897           default:
898             for(TInt iNode = 0; iNode < aNbNodes; iNode++) 
899               (*aConnectivity)[aSize+iNode] = aVector[iNode];
900           }
901         }
902
903         anElemNums->push_back(anElem->GetID());
904
905         if (anElemFamMap.find(anElem) != anElemFamMap.end())
906           aFamilyNums->push_back(anElemFamMap[anElem]);
907         else
908           aFamilyNums->push_back(myVolumesDefaultFamilyId);
909       }
910
911       if(TInt aNbElems = anTetraElemNums.size()){
912         PCellInfo aCellInfo = myMed->CrCellInfo(aMeshInfo,
913                                                 SMDS_MED_ENTITY,
914                                                 eTETRA4,
915                                                 aTetraConn,
916                                                 SMDS_MED_CONNECTIVITY,
917                                                 aTetraFamilyNums,
918                                                 anTetraElemNums);
919         MESSAGE("Perform - anEntity = "<<SMDS_MED_ENTITY<<"; aGeom = "<<eTETRA4<<"; aNbElems = "<<aNbElems);
920         myMed->SetCellInfo(aCellInfo);
921       }
922       if(TInt aNbElems = anPyraElemNums.size()){
923         PCellInfo aCellInfo = myMed->CrCellInfo(aMeshInfo,
924                                                 SMDS_MED_ENTITY,
925                                                 ePYRA5,
926                                                 aPyraConn,
927                                                 SMDS_MED_CONNECTIVITY,
928                                                 aPyraFamilyNums,
929                                                 anPyraElemNums);
930         MESSAGE("Perform - anEntity = "<<SMDS_MED_ENTITY<<"; aGeom = "<<ePYRA5<<"; aNbElems = "<<aNbElems);
931         myMed->SetCellInfo(aCellInfo);
932       }
933       if(TInt aNbElems = anPentaElemNums.size()){
934         PCellInfo aCellInfo = myMed->CrCellInfo(aMeshInfo,
935                                                 SMDS_MED_ENTITY,
936                                                 ePENTA6,
937                                                 aPentaConn,
938                                                 SMDS_MED_CONNECTIVITY,
939                                                 aPentaFamilyNums,
940                                                 anPentaElemNums);
941         MESSAGE("Perform - anEntity = "<<SMDS_MED_ENTITY<<"; aGeom = "<<ePENTA6<<"; aNbElems = "<<aNbElems);
942         myMed->SetCellInfo(aCellInfo);
943       }
944       if(TInt aNbElems = aHexaElemNums.size()){
945         PCellInfo aCellInfo = myMed->CrCellInfo(aMeshInfo,
946                                                 SMDS_MED_ENTITY,
947                                                 eHEXA8,
948                                                 aHexaConn,
949                                                 SMDS_MED_CONNECTIVITY,
950                                                 aHexaFamilyNums,
951                                                 aHexaElemNums);
952         MESSAGE("Perform - anEntity = "<<SMDS_MED_ENTITY<<"; aGeom = "<<eHEXA8<<"; aNbElems = "<<aNbElems);
953         myMed->SetCellInfo(aCellInfo);
954       }
955       if(TInt aNbElems = anTetra10ElemNums.size()){
956         PCellInfo aCellInfo = myMed->CrCellInfo(aMeshInfo,
957                                                 SMDS_MED_ENTITY,
958                                                 eTETRA10,
959                                                 aTetra10Conn,
960                                                 SMDS_MED_CONNECTIVITY,
961                                                 aTetra10FamilyNums,
962                                                 anTetra10ElemNums);
963         MESSAGE("Perform - anEntity = "<<SMDS_MED_ENTITY<<"; aGeom = "<<eTETRA10<<"; aNbElems = "<<aNbElems);
964         myMed->SetCellInfo(aCellInfo);
965       }
966       if(TInt aNbElems = anPyra13ElemNums.size()){
967         PCellInfo aCellInfo = myMed->CrCellInfo(aMeshInfo,
968                                                 SMDS_MED_ENTITY,
969                                                 ePYRA13,
970                                                 aPyra13Conn,
971                                                 SMDS_MED_CONNECTIVITY,
972                                                 aPyra13FamilyNums,
973                                                 anPyra13ElemNums);
974         MESSAGE("Perform - anEntity = "<<SMDS_MED_ENTITY<<"; aGeom = "<<ePYRA13<<"; aNbElems = "<<aNbElems);
975         myMed->SetCellInfo(aCellInfo);
976       }
977       if(TInt aNbElems = anPenta15ElemNums.size()){
978         PCellInfo aCellInfo = myMed->CrCellInfo(aMeshInfo,
979                                                 SMDS_MED_ENTITY,
980                                                 ePENTA15,
981                                                 aPenta15Conn,
982                                                 SMDS_MED_CONNECTIVITY,
983                                                 aPenta15FamilyNums,
984                                                 anPenta15ElemNums);
985         MESSAGE("Perform - anEntity = "<<SMDS_MED_ENTITY<<"; aGeom = "<<ePENTA15<<"; aNbElems = "<<aNbElems);
986         myMed->SetCellInfo(aCellInfo);
987       }
988       if(TInt aNbElems = aHexa20ElemNums.size()){
989         PCellInfo aCellInfo = myMed->CrCellInfo(aMeshInfo,
990                                                 SMDS_MED_ENTITY,
991                                                 eHEXA20,
992                                                 aHexa20Conn,
993                                                 SMDS_MED_CONNECTIVITY,
994                                                 aHexa20FamilyNums,
995                                                 aHexa20ElemNums);
996         MESSAGE("Perform - anEntity = "<<SMDS_MED_ENTITY<<"; aGeom = "<<eHEXA20<<"; aNbElems = "<<aNbElems);
997         myMed->SetCellInfo(aCellInfo);
998       }
999
1000       if(TInt aNbElems = aPolyedreElemNums.size()){
1001         // add one element in connectivities,
1002         // referenced by the last element in faces
1003         aPolyedreConn.push_back(0);
1004
1005         PPolyedreInfo aCellInfo = myMed->CrPolyedreInfo(aMeshInfo,
1006                                                         SMDS_MED_ENTITY,
1007                                                         ePOLYEDRE,
1008                                                         aPolyedreInds,
1009                                                         aPolyedreFaces,
1010                                                         aPolyedreConn,
1011                                                         SMDS_MED_CONNECTIVITY,
1012                                                         aPolyedreFamilyNums,
1013                                                         aPolyedreElemNums);
1014         MESSAGE("Perform - anEntity = "<<SMDS_MED_ENTITY<<"; aGeom = "<<ePOLYEDRE<<"; aNbElems = "<<aNbElems);
1015         myMed->SetPolyedreInfo(aCellInfo);
1016       }
1017     }
1018   }
1019   catch(const std::exception& exc) {
1020     INFOS("Follow exception was cought:\n\t"<<exc.what());
1021     throw;
1022   }
1023   catch(...) {
1024     INFOS("Unknown exception was cought !!!");
1025     throw;
1026   }
1027
1028   myMeshId = -1;
1029   myGroups.clear();
1030   mySubMeshes.clear();
1031   return aResult;
1032 }