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