Salome HOME
Join modifications from BR_Dev_For_4_0 tag V4_1_1.
[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         // PAL18941(a saved study with a mesh belong Z is opened and the mesh is belong X)
287         if ( aMeshDimension == 1 && !anIsXDimension ) // 1D only if mesh is along OX
288           if ( anIsYDimension ) {
289             aMeshDimension = 2;
290             anIsXDimension = true;
291           } else {
292             aMeshDimension = 3;
293           }
294       }
295
296       SMDS_NodeIteratorPtr aNodesIter = myMesh->nodesIterator();
297       switch(aMeshDimension){
298       case 3:
299         aCoordHelperPtr.reset(new TCoordHelper(aNodesIter,aXYZGetCoord,aXYZName));
300         break;
301       case 2:
302         if(anIsXDimension && anIsYDimension)
303           aCoordHelperPtr.reset(new TCoordHelper(aNodesIter,aXYGetCoord,aXYName));
304         if(anIsYDimension && anIsZDimension)
305           aCoordHelperPtr.reset(new TCoordHelper(aNodesIter,aYZGetCoord,aYZName));
306         if(anIsXDimension && anIsZDimension)
307           aCoordHelperPtr.reset(new TCoordHelper(aNodesIter,aXZGetCoord,aXZName));
308         break;
309       case 1:
310         if(anIsXDimension)
311           aCoordHelperPtr.reset(new TCoordHelper(aNodesIter,aXGetCoord,aXName));
312         if(anIsYDimension)
313           aCoordHelperPtr.reset(new TCoordHelper(aNodesIter,aYGetCoord,aYName));
314         if(anIsZDimension)
315           aCoordHelperPtr.reset(new TCoordHelper(aNodesIter,aZGetCoord,aZName));
316         break;
317       }
318     }
319
320     
321     PMeshInfo aMeshInfo = myMed->CrMeshInfo(aMeshDimension,aMeshName);
322     MESSAGE("Add - aMeshName : "<<aMeshName<<"; "<<aMeshInfo->GetName());
323     myMed->SetMeshInfo(aMeshInfo);
324
325     // Storing SMDS groups and sub-meshes
326     //-----------------------------------
327     int myNodesDefaultFamilyId   = 0;
328     int myEdgesDefaultFamilyId   = 0;
329     int myFacesDefaultFamilyId   = 0;
330     int myVolumesDefaultFamilyId = 0;
331     int nbNodes   = myMesh->NbNodes();
332     int nbEdges   = myMesh->NbEdges();
333     int nbFaces   = myMesh->NbFaces();
334     int nbVolumes = myMesh->NbVolumes();
335     if (myDoGroupOfNodes && nbNodes)
336       myNodesDefaultFamilyId = REST_NODES_FAMILY;
337     if (myDoGroupOfEdges && nbEdges)
338       myEdgesDefaultFamilyId = REST_EDGES_FAMILY;
339     if (myDoGroupOfFaces && nbFaces)
340       myFacesDefaultFamilyId = REST_FACES_FAMILY;
341     if (myDoGroupOfVolumes && nbVolumes)
342       myVolumesDefaultFamilyId = REST_VOLUMES_FAMILY;
343
344     MESSAGE("Perform - aFamilyInfo");
345     map<const SMDS_MeshElement *, int> anElemFamMap;
346     list<DriverMED_FamilyPtr> aFamilies;
347     if (myAllSubMeshes) {
348       aFamilies = DriverMED_Family::MakeFamilies
349         (myMesh->SubMeshes(), myGroups,
350          myDoGroupOfNodes   && nbNodes,
351          myDoGroupOfEdges   && nbEdges,
352          myDoGroupOfFaces   && nbFaces,
353          myDoGroupOfVolumes && nbVolumes);
354     } else {
355       aFamilies = DriverMED_Family::MakeFamilies
356         (mySubMeshes, myGroups,
357          myDoGroupOfNodes   && nbNodes,
358          myDoGroupOfEdges   && nbEdges,
359          myDoGroupOfFaces   && nbFaces,
360          myDoGroupOfVolumes && nbVolumes);
361     }
362     list<DriverMED_FamilyPtr>::iterator aFamsIter = aFamilies.begin();
363
364     for (; aFamsIter != aFamilies.end(); aFamsIter++)
365     {
366       PFamilyInfo aFamilyInfo = (*aFamsIter)->GetFamilyInfo(myMed,aMeshInfo);
367       myMed->SetFamilyInfo(aFamilyInfo);
368       int aFamId = (*aFamsIter)->GetId();
369
370       const set<const SMDS_MeshElement *>& anElems = (*aFamsIter)->GetElements();
371       set<const SMDS_MeshElement *>::const_iterator anElemsIter = anElems.begin();
372       for (; anElemsIter != anElems.end(); anElemsIter++)
373       {
374         anElemFamMap[*anElemsIter] = aFamId;
375       }
376     }
377
378     // Storing SMDS nodes to the MED file for the MED mesh
379     //----------------------------------------------------
380 #ifdef _EDF_NODE_IDS_
381     typedef map<TInt,TInt> TNodeIdMap;
382     TNodeIdMap aNodeIdMap;
383 #endif
384     TInt aNbElems = myMesh->NbNodes();
385     MED::TIntVector anElemNums(aNbElems);
386     MED::TIntVector aFamilyNums(aNbElems);
387     MED::TFloatVector aCoordinates(aNbElems*aMeshDimension);
388     for(TInt iNode = 0, aStartId = 0; aCoordHelperPtr->Next(); iNode++, aStartId += aMeshDimension){
389       for(TInt iCoord = 0; iCoord < aMeshDimension; iCoord++){
390         aCoordinates[aStartId+iCoord] = aCoordHelperPtr->GetCoord(iCoord);
391       }
392       int aNodeID = aCoordHelperPtr->GetID();
393       anElemNums[iNode] = aNodeID;
394 #ifdef _EDF_NODE_IDS_
395       aNodeIdMap[aNodeID] = iNode+1;
396 #endif
397       const SMDS_MeshNode* aNode = aCoordHelperPtr->GetNode();
398       if (anElemFamMap.find(aNode) != anElemFamMap.end())
399         aFamilyNums[iNode] = anElemFamMap[aNode];
400       else
401         aFamilyNums[iNode] = myNodesDefaultFamilyId;
402     }
403
404     MED::TStringVector aCoordNames(aMeshDimension);
405     MED::TStringVector aCoordUnits(aMeshDimension);
406     for(TInt iCoord = 0; iCoord < aMeshDimension; iCoord++){
407       aCoordNames[iCoord] = aCoordHelperPtr->GetName(iCoord);
408       aCoordUnits[iCoord] = aCoordHelperPtr->GetUnit(iCoord);
409     }
410
411     const ERepere SMDS_COORDINATE_SYSTEM = eCART;
412
413     PNodeInfo aNodeInfo = myMed->CrNodeInfo(aMeshInfo,
414                                             aCoordinates,
415                                             eFULL_INTERLACE,
416                                             SMDS_COORDINATE_SYSTEM,
417                                             aCoordNames,
418                                             aCoordUnits,
419                                             aFamilyNums,
420                                             anElemNums);
421     MESSAGE("Perform - aNodeInfo->GetNbElem() = "<<aNbElems);
422     myMed->SetNodeInfo(aNodeInfo);
423
424
425     // Storing others SMDS elements to the MED file for the MED mesh
426     //--------------------------------------------------------------
427     EEntiteMaillage SMDS_MED_ENTITY = eMAILLE;
428     const EConnectivite SMDS_MED_CONNECTIVITY = eNOD;
429
430     // Storing SMDS Edges
431     if(TInt aNbElems = myMesh->NbEdges()){
432 #ifdef _ELEMENTS_BY_DIM_
433       SMDS_MED_ENTITY = eARETE;
434 #endif
435       // count edges of diff types
436       int aNbSeg3 = 0, aNbSeg2 = 0;
437       SMDS_EdgeIteratorPtr anIter = myMesh->edgesIterator();
438       while ( anIter->more() )
439         if ( anIter->next()->NbNodes() == 3 )
440           ++aNbSeg3;
441       aNbSeg2 = aNbElems - aNbSeg3;
442
443       TInt aNbSeg2Conn = MED::GetNbNodes(eSEG2);
444       MED::TIntVector aSeg2ElemNums, aSeg2FamilyNums, aSeg2Conn;
445       aSeg2ElemNums  .reserve( aNbSeg2 );
446       aSeg2FamilyNums.reserve( aNbSeg2 );
447       aSeg2Conn      .reserve( aNbSeg2*aNbSeg2Conn );
448
449       TInt aNbSeg3Conn = MED::GetNbNodes(eSEG3);
450       MED::TIntVector aSeg3ElemNums, aSeg3FamilyNums, aSeg3Conn;
451       aSeg3ElemNums  .reserve( aNbSeg3 );
452       aSeg3FamilyNums.reserve( aNbSeg3 );
453       aSeg3Conn      .reserve( aNbSeg3*aNbSeg3Conn );
454
455       anIter = myMesh->edgesIterator();
456       while ( anIter->more() ) {
457         const SMDS_MeshEdge* anElem = anIter->next();
458         TInt aNbNodes = anElem->NbNodes();
459
460         TInt aNbConnectivity;
461         MED::TIntVector* anElemNums;
462         MED::TIntVector* aFamilyNums;
463         MED::TIntVector* aConnectivity;
464         switch(aNbNodes){
465         case 2:
466           aNbConnectivity = aNbSeg2Conn;
467           anElemNums      = &aSeg2ElemNums;
468           aFamilyNums     = &aSeg2FamilyNums;
469           aConnectivity   = &aSeg2Conn;
470           break;
471         case 3:
472           aNbConnectivity = aNbSeg3Conn;
473           anElemNums      = &aSeg3ElemNums;
474           aFamilyNums     = &aSeg3FamilyNums;
475           aConnectivity   = &aSeg3Conn;
476           break;
477         default:
478           break;
479         }
480
481         for(TInt iNode = 0; iNode < aNbNodes; iNode++) {
482           const SMDS_MeshElement* aNode = anElem->GetNode( iNode );
483 #ifdef _EDF_NODE_IDS_
484           aConnectivity->push_back( aNodeIdMap[aNode->GetID()] );
485 #else
486           aConnectivity->push_back( aNode->GetID() );
487 #endif
488         }
489
490         anElemNums->push_back(anElem->GetID());
491
492         map<const SMDS_MeshElement*,int>::iterator edge_fam = anElemFamMap.find( anElem );
493         if ( edge_fam != anElemFamMap.end() )
494           aFamilyNums->push_back( edge_fam->second );
495         else
496           aFamilyNums->push_back( myEdgesDefaultFamilyId );
497       }
498       
499       if ( aNbSeg2 ) {
500         PCellInfo aCellInfo = myMed->CrCellInfo(aMeshInfo,
501                                                 SMDS_MED_ENTITY,
502                                                 eSEG2,
503                                                 aSeg2Conn,
504                                                 SMDS_MED_CONNECTIVITY,
505                                                 aSeg2FamilyNums,
506                                                 aSeg2ElemNums);
507         myMed->SetCellInfo(aCellInfo);
508       }
509       if ( aNbSeg3 ) {
510         PCellInfo aCellInfo = myMed->CrCellInfo(aMeshInfo,
511                                                 SMDS_MED_ENTITY,
512                                                 eSEG3,
513                                                 aSeg3Conn,
514                                                 SMDS_MED_CONNECTIVITY,
515                                                 aSeg3FamilyNums,
516                                                 aSeg3ElemNums);
517         myMed->SetCellInfo(aCellInfo);
518       }
519     }
520
521     // Storing SMDS Faces
522     if(TInt aNbElems = myMesh->NbFaces()){
523       SMDS_FaceIteratorPtr anIter = myMesh->facesIterator();
524 #ifdef _ELEMENTS_BY_DIM_
525       SMDS_MED_ENTITY = eFACE;
526 #endif
527       TInt aNbTriaConn = MED::GetNbNodes(eTRIA3);
528       MED::TIntVector anTriaElemNums; 
529       anTriaElemNums.reserve(aNbElems);
530       MED::TIntVector aTriaFamilyNums;
531       aTriaFamilyNums.reserve(aNbElems);
532       MED::TIntVector aTriaConn;
533       aTriaConn.reserve(aNbElems*aNbTriaConn);
534
535       TInt aNbTria6Conn = MED::GetNbNodes(eTRIA6);
536       MED::TIntVector anTria6ElemNums; 
537       anTria6ElemNums.reserve(aNbElems);
538       MED::TIntVector aTria6FamilyNums;
539       aTria6FamilyNums.reserve(aNbElems);
540       MED::TIntVector aTria6Conn;
541       aTria6Conn.reserve(aNbElems*aNbTria6Conn);
542
543       TInt aNbQuadConn = MED::GetNbNodes(eQUAD4);
544       MED::TIntVector aQuadElemNums;
545       aQuadElemNums.reserve(aNbElems);
546       MED::TIntVector aQuadFamilyNums;
547       aQuadFamilyNums.reserve(aNbElems);
548       MED::TIntVector aQuadConn;
549       aQuadConn.reserve(aNbElems*aNbQuadConn);
550
551       TInt aNbQuad8Conn = MED::GetNbNodes(eQUAD8);
552       MED::TIntVector aQuad8ElemNums;
553       aQuad8ElemNums.reserve(aNbElems);
554       MED::TIntVector aQuad8FamilyNums;
555       aQuad8FamilyNums.reserve(aNbElems);
556       MED::TIntVector aQuad8Conn;
557       aQuad8Conn.reserve(aNbElems*aNbQuad8Conn);
558
559       MED::TIntVector aPolygoneElemNums;
560       aPolygoneElemNums.reserve(aNbElems);
561       MED::TIntVector aPolygoneInds;
562       aPolygoneInds.reserve(aNbElems + 1);
563       aPolygoneInds.push_back(1); // reference on the first element in the connectivities
564       MED::TIntVector aPolygoneFamilyNums;
565       aPolygoneFamilyNums.reserve(aNbElems);
566       MED::TIntVector aPolygoneConn;
567       aPolygoneConn.reserve(aNbElems*aNbQuadConn);
568
569       for(TInt iElem = 0; iElem < aNbElems && anIter->more(); iElem++){
570         const SMDS_MeshFace* anElem = anIter->next();
571         TInt aNbNodes = anElem->NbNodes();
572         SMDS_ElemIteratorPtr aNodesIter = anElem->nodesIterator();
573         TInt aNbConnectivity;
574         MED::TIntVector* anElemNums;
575         MED::TIntVector* aFamilyNums;
576         MED::TIntVector* aConnectivity;
577         if (anElem->IsPoly()) {
578           aNbConnectivity = aNbNodes;
579           anElemNums = &aPolygoneElemNums;
580           aFamilyNums = &aPolygoneFamilyNums;
581           aConnectivity = &aPolygoneConn;
582         }
583         else {
584           switch(aNbNodes){
585           case 3:
586             aNbConnectivity = aNbTriaConn;
587             anElemNums = &anTriaElemNums;
588             aFamilyNums = &aTriaFamilyNums;
589             aConnectivity = &aTriaConn;
590             break;
591           case 4:
592             aNbConnectivity = aNbQuadConn;
593             anElemNums = &aQuadElemNums;
594             aFamilyNums = &aQuadFamilyNums;
595             aConnectivity = &aQuadConn;
596             break;
597           case 6:
598             aNbConnectivity = aNbTria6Conn;
599             anElemNums = &anTria6ElemNums;
600             aFamilyNums = &aTria6FamilyNums;
601             aConnectivity = &aTria6Conn;
602             break;
603           case 8:
604             aNbConnectivity = aNbQuad8Conn;
605             anElemNums = &aQuad8ElemNums;
606             aFamilyNums = &aQuad8FamilyNums;
607             aConnectivity = &aQuad8Conn;
608             break;
609           default:
610             break;
611           }
612         }
613         MED::TIntVector aVector(aNbNodes);
614         for(TInt iNode = 0; aNodesIter->more(); iNode++){
615           const SMDS_MeshElement* aNode = aNodesIter->next();
616 #ifdef _EDF_NODE_IDS_
617           aVector[iNode] = aNodeIdMap[aNode->GetID()];
618 #else
619           aVector[iNode] = aNode->GetID();
620 #endif
621         }
622
623         TInt aSize = aConnectivity->size();
624         aConnectivity->resize(aSize+aNbConnectivity);
625         // There is some differences between SMDS and MED in cells mapping
626         switch(aNbNodes){
627         case 4:
628           (*aConnectivity)[aSize+0] = aVector[0];
629           (*aConnectivity)[aSize+1] = aVector[1];
630           (*aConnectivity)[aSize+2] = aVector[3];  
631           (*aConnectivity)[aSize+3] = aVector[2];  
632         default:
633           for(TInt iNode = 0; iNode < aNbNodes; iNode++) 
634             (*aConnectivity)[aSize+iNode] = aVector[iNode];
635         }
636
637         if (anElem->IsPoly()) {
638           // fill indices for polygonal element
639           TInt aPrevPos = aPolygoneInds.back();
640           aPolygoneInds.push_back(aPrevPos + aNbNodes);
641         }
642
643         anElemNums->push_back(anElem->GetID());
644
645         if (anElemFamMap.find(anElem) != anElemFamMap.end())
646           aFamilyNums->push_back(anElemFamMap[anElem]);
647         else
648           aFamilyNums->push_back(myFacesDefaultFamilyId);
649       }
650       if(TInt aNbElems = anTriaElemNums.size()){
651         PCellInfo aCellInfo = myMed->CrCellInfo(aMeshInfo,
652                                                 SMDS_MED_ENTITY,
653                                                 eTRIA3,
654                                                 aTriaConn,
655                                                 SMDS_MED_CONNECTIVITY,
656                                                 aTriaFamilyNums,
657                                                 anTriaElemNums);
658         MESSAGE("Perform - anEntity = "<<SMDS_MED_ENTITY<<"; aGeom = "<<eTRIA3<<"; aNbElems = "<<aNbElems);
659         myMed->SetCellInfo(aCellInfo);
660       }
661       if(TInt aNbElems = aQuadElemNums.size()){
662         PCellInfo aCellInfo = myMed->CrCellInfo(aMeshInfo,
663                                                 SMDS_MED_ENTITY,
664                                                 eQUAD4,
665                                                 aQuadConn,
666                                                 SMDS_MED_CONNECTIVITY,
667                                                 aQuadFamilyNums,
668                                                 aQuadElemNums);
669         MESSAGE("Perform - anEntity = "<<SMDS_MED_ENTITY<<"; aGeom = "<<eQUAD4<<"; aNbElems = "<<aNbElems);
670         myMed->SetCellInfo(aCellInfo);
671       }
672       if(TInt aNbElems = anTria6ElemNums.size()){
673         PCellInfo aCellInfo = myMed->CrCellInfo(aMeshInfo,
674                                                 SMDS_MED_ENTITY,
675                                                 eTRIA6,
676                                                 aTria6Conn,
677                                                 SMDS_MED_CONNECTIVITY,
678                                                 aTria6FamilyNums,
679                                                 anTria6ElemNums);
680         MESSAGE("Perform - anEntity = "<<SMDS_MED_ENTITY<<"; aGeom = "<<eTRIA6<<"; aNbElems = "<<aNbElems);
681         myMed->SetCellInfo(aCellInfo);
682       }
683       if(TInt aNbElems = aQuad8ElemNums.size()){
684         PCellInfo aCellInfo = myMed->CrCellInfo(aMeshInfo,
685                                                 SMDS_MED_ENTITY,
686                                                 eQUAD8,
687                                                 aQuad8Conn,
688                                                 SMDS_MED_CONNECTIVITY,
689                                                 aQuad8FamilyNums,
690                                                 aQuad8ElemNums);
691         MESSAGE("Perform - anEntity = "<<SMDS_MED_ENTITY<<"; aGeom = "<<eQUAD8<<"; aNbElems = "<<aNbElems);
692         myMed->SetCellInfo(aCellInfo);
693       }
694       if(TInt aNbElems = aPolygoneElemNums.size()){
695         // add one element in connectivities,
696         // referenced by the last element in indices
697         aPolygoneConn.push_back(0);
698
699         PPolygoneInfo aCellInfo = myMed->CrPolygoneInfo(aMeshInfo,
700                                                         SMDS_MED_ENTITY,
701                                                         ePOLYGONE,
702                                                         aPolygoneInds,
703                                                         aPolygoneConn,
704                                                         SMDS_MED_CONNECTIVITY,
705                                                         aPolygoneFamilyNums,
706                                                         aPolygoneElemNums);
707         MESSAGE("Perform - anEntity = "<<SMDS_MED_ENTITY<<"; aGeom = "<<ePOLYGONE<<"; aNbElems = "<<aNbElems);
708         myMed->SetPolygoneInfo(aCellInfo);
709       }
710     }
711
712     // Storing SMDS Volumes
713     if(TInt aNbElems = myMesh->NbVolumes()){
714       SMDS_VolumeIteratorPtr anIter = myMesh->volumesIterator();
715 #ifdef _ELEMENTS_BY_DIM_
716       SMDS_MED_ENTITY = eMAILLE;
717 #endif
718       TInt aNbTetraConn = MED::GetNbNodes(eTETRA4);
719       MED::TIntVector anTetraElemNums; 
720       anTetraElemNums.reserve(aNbElems);
721       MED::TIntVector aTetraFamilyNums;
722       aTetraFamilyNums.reserve(aNbElems);
723       MED::TIntVector aTetraConn;
724       aTetraConn.reserve(aNbElems*aNbTetraConn);
725
726       TInt aNbPyraConn = MED::GetNbNodes(ePYRA5);
727       MED::TIntVector anPyraElemNums; 
728       anPyraElemNums.reserve(aNbElems);
729       MED::TIntVector aPyraFamilyNums;
730       aPyraFamilyNums.reserve(aNbElems);
731       MED::TIntVector aPyraConn;
732       aPyraConn.reserve(aNbElems*aNbPyraConn);
733
734       TInt aNbPentaConn = MED::GetNbNodes(ePENTA6);
735       MED::TIntVector anPentaElemNums; 
736       anPentaElemNums.reserve(aNbElems);
737       MED::TIntVector aPentaFamilyNums;
738       aPentaFamilyNums.reserve(aNbElems);
739       MED::TIntVector aPentaConn;
740       aPentaConn.reserve(aNbElems*aNbPentaConn);
741
742       TInt aNbHexaConn = MED::GetNbNodes(eHEXA8);
743       MED::TIntVector aHexaElemNums;
744       aHexaElemNums.reserve(aNbElems);
745       MED::TIntVector aHexaFamilyNums;
746       aHexaFamilyNums.reserve(aNbElems);
747       MED::TIntVector aHexaConn;
748       aHexaConn.reserve(aNbElems*aNbHexaConn);
749
750       TInt aNbTetra10Conn = MED::GetNbNodes(eTETRA10);
751       MED::TIntVector anTetra10ElemNums; 
752       anTetra10ElemNums.reserve(aNbElems);
753       MED::TIntVector aTetra10FamilyNums;
754       aTetra10FamilyNums.reserve(aNbElems);
755       MED::TIntVector aTetra10Conn;
756       aTetra10Conn.reserve(aNbElems*aNbTetra10Conn);
757
758       TInt aNbPyra13Conn = MED::GetNbNodes(ePYRA13);
759       MED::TIntVector anPyra13ElemNums; 
760       anPyra13ElemNums.reserve(aNbElems);
761       MED::TIntVector aPyra13FamilyNums;
762       aPyra13FamilyNums.reserve(aNbElems);
763       MED::TIntVector aPyra13Conn;
764       aPyra13Conn.reserve(aNbElems*aNbPyra13Conn);
765
766       TInt aNbPenta15Conn = MED::GetNbNodes(ePENTA15);
767       MED::TIntVector anPenta15ElemNums; 
768       anPenta15ElemNums.reserve(aNbElems);
769       MED::TIntVector aPenta15FamilyNums;
770       aPenta15FamilyNums.reserve(aNbElems);
771       MED::TIntVector aPenta15Conn;
772       aPenta15Conn.reserve(aNbElems*aNbPenta15Conn);
773
774       TInt aNbHexa20Conn = MED::GetNbNodes(eHEXA20);
775       MED::TIntVector aHexa20ElemNums;
776       aHexa20ElemNums.reserve(aNbElems);
777       MED::TIntVector aHexa20FamilyNums;
778       aHexa20FamilyNums.reserve(aNbElems);
779       MED::TIntVector aHexa20Conn;
780       aHexa20Conn.reserve(aNbElems*aNbHexa20Conn);
781
782       MED::TIntVector aPolyedreElemNums;
783       aPolyedreElemNums.reserve(aNbElems);
784       MED::TIntVector aPolyedreInds;
785       aPolyedreInds.reserve(aNbElems + 1);
786       aPolyedreInds.push_back(1); // reference on the first element in the faces
787       MED::TIntVector aPolyedreFaces;
788       aPolyedreFaces.reserve(aNbElems + 1);
789       aPolyedreFaces.push_back(1); // reference on the first element in the connectivities
790       MED::TIntVector aPolyedreFamilyNums;
791       aPolyedreFamilyNums.reserve(aNbElems);
792       MED::TIntVector aPolyedreConn;
793       aPolyedreConn.reserve(aNbElems*aNbHexaConn);
794
795       for(TInt iElem = 0; iElem < aNbElems && anIter->more(); iElem++){
796         const SMDS_MeshVolume* anElem = anIter->next();
797
798         MED::TIntVector* anElemNums;
799         MED::TIntVector* aFamilyNums;
800
801         if (anElem->IsPoly()) {
802           const SMDS_PolyhedralVolumeOfNodes* aPolyedre =
803             (const SMDS_PolyhedralVolumeOfNodes*) anElem;
804           if (!aPolyedre) {
805             MESSAGE("Warning: bad volumic element");
806             continue;
807           }
808
809           anElemNums = &aPolyedreElemNums;
810           aFamilyNums = &aPolyedreFamilyNums;
811
812           TInt aNodeId, aNbFaces = aPolyedre->NbFaces();
813           for (int iface = 1; iface <= aNbFaces; iface++) {
814             int aNbFaceNodes = aPolyedre->NbFaceNodes(iface);
815             for (int inode = 1; inode <= aNbFaceNodes; inode++) {
816               aNodeId = aPolyedre->GetFaceNode(iface, inode)->GetID();
817 #ifdef _EDF_NODE_IDS_
818               aPolyedreConn.push_back(aNodeIdMap[aNodeId]);
819 #else
820               aPolyedreConn.push_back(aNodeId);
821 #endif
822             }
823             TInt aPrevPos = aPolyedreFaces.back();
824             aPolyedreFaces.push_back(aPrevPos + aNbFaceNodes);
825           }
826           TInt aPrevPos = aPolyedreInds.back();
827           aPolyedreInds.push_back(aPrevPos + aNbFaces);
828
829         }
830         else {
831           TInt aNbNodes = anElem->NbNodes();
832           SMDS_ElemIteratorPtr aNodesIter = anElem->nodesIterator();
833           TInt aNbConnectivity;
834           MED::TIntVector* aConnectivity;
835           switch(aNbNodes){
836           case 4:
837             aNbConnectivity = aNbTetraConn;
838             anElemNums = &anTetraElemNums;
839             aFamilyNums = &aTetraFamilyNums;
840             aConnectivity = &aTetraConn;
841             break;
842           case 5:
843             aNbConnectivity = aNbPyraConn;
844             anElemNums = &anPyraElemNums;
845             aFamilyNums = &aPyraFamilyNums;
846             aConnectivity = &aPyraConn;
847             break;
848           case 6:
849             aNbConnectivity = aNbPentaConn;
850             anElemNums = &anPentaElemNums;
851             aFamilyNums = &aPentaFamilyNums;
852             aConnectivity = &aPentaConn;
853             break;
854           case 8:
855             aNbConnectivity = aNbHexaConn;
856             anElemNums = &aHexaElemNums;
857             aFamilyNums = &aHexaFamilyNums;
858             aConnectivity = &aHexaConn;
859             break;
860           case 10:
861             aNbConnectivity = aNbTetra10Conn;
862             anElemNums = &anTetra10ElemNums;
863             aFamilyNums = &aTetra10FamilyNums;
864             aConnectivity = &aTetra10Conn;
865             break;
866           case 13:
867             aNbConnectivity = aNbPyra13Conn;
868             anElemNums = &anPyra13ElemNums;
869             aFamilyNums = &aPyra13FamilyNums;
870             aConnectivity = &aPyra13Conn;
871             break;
872           case 15:
873             aNbConnectivity = aNbPenta15Conn;
874             anElemNums = &anPenta15ElemNums;
875             aFamilyNums = &aPenta15FamilyNums;
876             aConnectivity = &aPenta15Conn;
877             break;
878           case 20:
879             aNbConnectivity = aNbHexa20Conn;
880             anElemNums = &aHexa20ElemNums;
881             aFamilyNums = &aHexa20FamilyNums;
882             aConnectivity = &aHexa20Conn;
883           }
884
885           TInt aSize = aConnectivity->size();
886           aConnectivity->resize(aSize + aNbConnectivity);
887
888           MED::TIntVector aVector(aNbNodes);
889           for(TInt iNode = 0; aNodesIter->more(); iNode++){
890             const SMDS_MeshElement* aNode = aNodesIter->next();
891 #ifdef _EDF_NODE_IDS_
892             aVector[iNode] = aNodeIdMap[aNode->GetID()];
893 #else
894             aVector[iNode] = aNode->GetID();
895 #endif
896           }
897           // There is some difference between SMDS and MED in cells mapping
898           switch(aNbNodes){
899           case 5:
900             (*aConnectivity)[aSize+0] = aVector[0];
901             (*aConnectivity)[aSize+1] = aVector[3];
902             (*aConnectivity)[aSize+2] = aVector[2];  
903             (*aConnectivity)[aSize+3] = aVector[1];  
904             (*aConnectivity)[aSize+4] = aVector[4];  
905           default:
906             for(TInt iNode = 0; iNode < aNbNodes; iNode++) 
907               (*aConnectivity)[aSize+iNode] = aVector[iNode];
908           }
909         }
910
911         anElemNums->push_back(anElem->GetID());
912
913         if (anElemFamMap.find(anElem) != anElemFamMap.end())
914           aFamilyNums->push_back(anElemFamMap[anElem]);
915         else
916           aFamilyNums->push_back(myVolumesDefaultFamilyId);
917       }
918
919       if(TInt aNbElems = anTetraElemNums.size()){
920         PCellInfo aCellInfo = myMed->CrCellInfo(aMeshInfo,
921                                                 SMDS_MED_ENTITY,
922                                                 eTETRA4,
923                                                 aTetraConn,
924                                                 SMDS_MED_CONNECTIVITY,
925                                                 aTetraFamilyNums,
926                                                 anTetraElemNums);
927         MESSAGE("Perform - anEntity = "<<SMDS_MED_ENTITY<<"; aGeom = "<<eTETRA4<<"; aNbElems = "<<aNbElems);
928         myMed->SetCellInfo(aCellInfo);
929       }
930       if(TInt aNbElems = anPyraElemNums.size()){
931         PCellInfo aCellInfo = myMed->CrCellInfo(aMeshInfo,
932                                                 SMDS_MED_ENTITY,
933                                                 ePYRA5,
934                                                 aPyraConn,
935                                                 SMDS_MED_CONNECTIVITY,
936                                                 aPyraFamilyNums,
937                                                 anPyraElemNums);
938         MESSAGE("Perform - anEntity = "<<SMDS_MED_ENTITY<<"; aGeom = "<<ePYRA5<<"; aNbElems = "<<aNbElems);
939         myMed->SetCellInfo(aCellInfo);
940       }
941       if(TInt aNbElems = anPentaElemNums.size()){
942         PCellInfo aCellInfo = myMed->CrCellInfo(aMeshInfo,
943                                                 SMDS_MED_ENTITY,
944                                                 ePENTA6,
945                                                 aPentaConn,
946                                                 SMDS_MED_CONNECTIVITY,
947                                                 aPentaFamilyNums,
948                                                 anPentaElemNums);
949         MESSAGE("Perform - anEntity = "<<SMDS_MED_ENTITY<<"; aGeom = "<<ePENTA6<<"; aNbElems = "<<aNbElems);
950         myMed->SetCellInfo(aCellInfo);
951       }
952       if(TInt aNbElems = aHexaElemNums.size()){
953         PCellInfo aCellInfo = myMed->CrCellInfo(aMeshInfo,
954                                                 SMDS_MED_ENTITY,
955                                                 eHEXA8,
956                                                 aHexaConn,
957                                                 SMDS_MED_CONNECTIVITY,
958                                                 aHexaFamilyNums,
959                                                 aHexaElemNums);
960         MESSAGE("Perform - anEntity = "<<SMDS_MED_ENTITY<<"; aGeom = "<<eHEXA8<<"; aNbElems = "<<aNbElems);
961         myMed->SetCellInfo(aCellInfo);
962       }
963       if(TInt aNbElems = anTetra10ElemNums.size()){
964         PCellInfo aCellInfo = myMed->CrCellInfo(aMeshInfo,
965                                                 SMDS_MED_ENTITY,
966                                                 eTETRA10,
967                                                 aTetra10Conn,
968                                                 SMDS_MED_CONNECTIVITY,
969                                                 aTetra10FamilyNums,
970                                                 anTetra10ElemNums);
971         MESSAGE("Perform - anEntity = "<<SMDS_MED_ENTITY<<"; aGeom = "<<eTETRA10<<"; aNbElems = "<<aNbElems);
972         myMed->SetCellInfo(aCellInfo);
973       }
974       if(TInt aNbElems = anPyra13ElemNums.size()){
975         PCellInfo aCellInfo = myMed->CrCellInfo(aMeshInfo,
976                                                 SMDS_MED_ENTITY,
977                                                 ePYRA13,
978                                                 aPyra13Conn,
979                                                 SMDS_MED_CONNECTIVITY,
980                                                 aPyra13FamilyNums,
981                                                 anPyra13ElemNums);
982         MESSAGE("Perform - anEntity = "<<SMDS_MED_ENTITY<<"; aGeom = "<<ePYRA13<<"; aNbElems = "<<aNbElems);
983         myMed->SetCellInfo(aCellInfo);
984       }
985       if(TInt aNbElems = anPenta15ElemNums.size()){
986         PCellInfo aCellInfo = myMed->CrCellInfo(aMeshInfo,
987                                                 SMDS_MED_ENTITY,
988                                                 ePENTA15,
989                                                 aPenta15Conn,
990                                                 SMDS_MED_CONNECTIVITY,
991                                                 aPenta15FamilyNums,
992                                                 anPenta15ElemNums);
993         MESSAGE("Perform - anEntity = "<<SMDS_MED_ENTITY<<"; aGeom = "<<ePENTA15<<"; aNbElems = "<<aNbElems);
994         myMed->SetCellInfo(aCellInfo);
995       }
996       if(TInt aNbElems = aHexa20ElemNums.size()){
997         PCellInfo aCellInfo = myMed->CrCellInfo(aMeshInfo,
998                                                 SMDS_MED_ENTITY,
999                                                 eHEXA20,
1000                                                 aHexa20Conn,
1001                                                 SMDS_MED_CONNECTIVITY,
1002                                                 aHexa20FamilyNums,
1003                                                 aHexa20ElemNums);
1004         MESSAGE("Perform - anEntity = "<<SMDS_MED_ENTITY<<"; aGeom = "<<eHEXA20<<"; aNbElems = "<<aNbElems);
1005         myMed->SetCellInfo(aCellInfo);
1006       }
1007
1008       if(TInt aNbElems = aPolyedreElemNums.size()){
1009         // add one element in connectivities,
1010         // referenced by the last element in faces
1011         aPolyedreConn.push_back(0);
1012
1013         PPolyedreInfo aCellInfo = myMed->CrPolyedreInfo(aMeshInfo,
1014                                                         SMDS_MED_ENTITY,
1015                                                         ePOLYEDRE,
1016                                                         aPolyedreInds,
1017                                                         aPolyedreFaces,
1018                                                         aPolyedreConn,
1019                                                         SMDS_MED_CONNECTIVITY,
1020                                                         aPolyedreFamilyNums,
1021                                                         aPolyedreElemNums);
1022         MESSAGE("Perform - anEntity = "<<SMDS_MED_ENTITY<<"; aGeom = "<<ePOLYEDRE<<"; aNbElems = "<<aNbElems);
1023         myMed->SetPolyedreInfo(aCellInfo);
1024       }
1025     }
1026   }
1027   catch(const std::exception& exc) {
1028     INFOS("Follow exception was cought:\n\t"<<exc.what());
1029     throw;
1030   }
1031   catch(...) {
1032     INFOS("Unknown exception was cought !!!");
1033     throw;
1034   }
1035
1036   myMeshId = -1;
1037   myGroups.clear();
1038   mySubMeshes.clear();
1039   return aResult;
1040 }