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