Salome HOME
145a13c9319d6efabfc2975bcfb14b61295bff84
[modules/smesh.git] / src / DriverMED / DriverMED_R_SMESHDS_Mesh.cxx
1 //  Copyright (C) 2007-2008  CEA/DEN, EDF R&D, OPEN CASCADE
2 //
3 //  Copyright (C) 2003-2007  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 //  SMESH DriverMED : driver to read and write 'med' files
23 //  File   : DriverMED_R_SMESHDS_Mesh.cxx
24 //  Module : SMESH
25 //
26 #include "DriverMED_R_SMESHDS_Mesh.h"
27 #include "DriverMED_R_SMDS_Mesh.h"
28 #include "SMESHDS_Mesh.hxx"
29 #include "utilities.h"
30
31 #include "DriverMED_Family.h"
32
33 #include "SMESHDS_Group.hxx"
34
35 #include "MED_Factory.hxx"
36 #include "MED_CoordUtils.hxx"
37 #include "MED_Utilities.hxx"
38
39 #include <stdlib.h>
40
41 #ifdef _DEBUG_
42 static int MYDEBUG = 0;
43 //#define _DEXCEPT_
44 #else
45 static int MYDEBUG = 0;
46 #endif
47
48 #define _EDF_NODE_IDS_
49
50 using namespace MED;
51
52 void
53 DriverMED_R_SMESHDS_Mesh
54 ::SetMeshName(std::string theMeshName)
55 {
56   myMeshName = theMeshName;
57 }
58
59 static const SMDS_MeshNode* 
60 FindNode(const SMDS_Mesh* theMesh, TInt theId){
61   const SMDS_MeshNode* aNode = theMesh->FindNode(theId);
62   if(aNode) return aNode;
63   EXCEPTION(std::runtime_error,"SMDS_Mesh::FindNode - cannot find a SMDS_MeshNode for ID = "<<theId);
64 }
65
66
67 Driver_Mesh::Status 
68 DriverMED_R_SMESHDS_Mesh
69 ::Perform()
70 {
71   Status aResult = DRS_FAIL;
72 #ifndef _DEXCEPT_
73   try{
74 #endif
75     myFamilies.clear();
76     if(MYDEBUG) MESSAGE("Perform - myFile : "<<myFile);
77     PWrapper aMed = CrWrapper(myFile,true);
78
79     aResult = DRS_EMPTY;
80     if(TInt aNbMeshes = aMed->GetNbMeshes()){
81       for(int iMesh = 0; iMesh < aNbMeshes; iMesh++){
82         // Reading the MED mesh
83         //---------------------
84         PMeshInfo aMeshInfo = aMed->GetPMeshInfo(iMesh+1);
85
86         std::string aMeshName;
87         if (myMeshId != -1) {
88           std::ostringstream aMeshNameStr;
89           aMeshNameStr<<myMeshId;
90           aMeshName = aMeshNameStr.str();
91         } else {
92           aMeshName = myMeshName;
93         }
94         if(MYDEBUG) MESSAGE("Perform - aMeshName : "<<aMeshName<<"; "<<aMeshInfo->GetName());
95         if(aMeshName != aMeshInfo->GetName()) continue;
96         aResult = DRS_OK;
97
98         //TInt aMeshDim = aMeshInfo->GetDim();
99         
100         // Reading MED families to the temporary structure
101         //------------------------------------------------
102         TErr anErr;
103         TInt aNbFams = aMed->GetNbFamilies(aMeshInfo);
104         if(MYDEBUG) MESSAGE("Read " << aNbFams << " families");
105         for (TInt iFam = 0; iFam < aNbFams; iFam++) {
106           PFamilyInfo aFamilyInfo = aMed->GetPFamilyInfo(aMeshInfo,iFam+1,&anErr);
107           if(anErr >= 0){
108             TInt aFamId = aFamilyInfo->GetId();
109             if(MYDEBUG) MESSAGE("Family " << aFamId << " :");
110             
111             DriverMED_FamilyPtr aFamily (new DriverMED_Family);
112             
113             TInt aNbGrp = aFamilyInfo->GetNbGroup();
114             if(MYDEBUG) MESSAGE("belong to " << aNbGrp << " groups");
115             bool isAttrOk = false;
116             if(aFamilyInfo->GetNbAttr() == aNbGrp)
117               isAttrOk = true;
118             for (TInt iGr = 0; iGr < aNbGrp; iGr++) {
119               std::string aGroupName = aFamilyInfo->GetGroupName(iGr);
120               if(isAttrOk){
121                 TInt anAttrVal = aFamilyInfo->GetAttrVal(iGr);
122                 aFamily->SetGroupAttributVal(anAttrVal);
123               }
124               
125               if(MYDEBUG) MESSAGE(aGroupName);
126               aFamily->AddGroupName(aGroupName);
127               
128             }
129             aFamily->SetId( aFamId );
130             myFamilies[aFamId] = aFamily;
131           }
132         }
133
134         if (aMeshInfo->GetType() == MED::eSTRUCTURE){
135           /*bool aRes = */buildMeshGrille(aMed,aMeshInfo);
136           continue;
137         }
138
139         // Reading MED nodes to the corresponding SMDS structure
140         //------------------------------------------------------
141         PNodeInfo aNodeInfo = aMed->GetPNodeInfo(aMeshInfo);
142         if (!aNodeInfo) {
143           aResult = DRS_FAIL;
144           continue;
145         }
146
147         PCoordHelper aCoordHelper = GetCoordHelper(aNodeInfo);
148
149         EBooleen anIsNodeNum = aNodeInfo->IsElemNum();
150         TInt aNbElems = aNodeInfo->GetNbElem();
151         if(MYDEBUG) MESSAGE("Perform - aNodeInfo->GetNbElem() = "<<aNbElems<<"; anIsNodeNum = "<<anIsNodeNum);
152         DriverMED_FamilyPtr aFamily;
153         for(TInt iElem = 0; iElem < aNbElems; iElem++){
154           TCCoordSlice aCoordSlice = aNodeInfo->GetCoordSlice(iElem);
155           double aCoords[3] = {0.0, 0.0, 0.0};
156           for(TInt iDim = 0; iDim < 3; iDim++)
157             aCoords[iDim] = aCoordHelper->GetCoord(aCoordSlice,iDim);
158           const SMDS_MeshNode* aNode;
159           if(anIsNodeNum) {
160             aNode = myMesh->AddNodeWithID
161               (aCoords[0],aCoords[1],aCoords[2],aNodeInfo->GetElemNum(iElem));
162           } else {
163             aNode = myMesh->AddNode
164               (aCoords[0],aCoords[1],aCoords[2]);
165           }
166           //cout<<aNode->GetID()<<": "<<aNode->X()<<", "<<aNode->Y()<<", "<<aNode->Z()<<endl;
167
168           // Save reference to this node from its family
169           TInt aFamNum = aNodeInfo->GetFamNum(iElem);
170           if ( checkFamilyID ( aFamily, aFamNum ))
171           {
172             aFamily->AddElement(aNode);
173             aFamily->SetType(SMDSAbs_Node);
174           }
175         }
176
177         // Reading pre information about all MED cells
178         //--------------------------------------------
179         typedef MED::TVector<int> TNodeIds;
180         bool takeNumbers = true;  // initially we trust the numbers from file
181         MED::TEntityInfo aEntityInfo = aMed->GetEntityInfo(aMeshInfo);
182         MED::TEntityInfo::iterator anEntityIter = aEntityInfo.begin();
183         for(; anEntityIter != aEntityInfo.end(); anEntityIter++){
184           const EEntiteMaillage& anEntity = anEntityIter->first;
185           if(anEntity == eNOEUD) continue;
186           // Reading MED cells to the corresponding SMDS structure
187           //------------------------------------------------------
188           const MED::TGeom2Size& aGeom2Size = anEntityIter->second;
189           MED::TGeom2Size::const_iterator aGeom2SizeIter = aGeom2Size.begin();
190           for(; aGeom2SizeIter != aGeom2Size.end(); aGeom2SizeIter++){
191             const EGeometrieElement& aGeom = aGeom2SizeIter->first;
192
193             switch(aGeom) {
194 //          case ePOINT1: ## PAL16410
195 //            break;
196             case ePOLYGONE: {
197               PPolygoneInfo aPolygoneInfo = aMed->GetPPolygoneInfo(aMeshInfo,anEntity,aGeom);
198               EBooleen anIsElemNum = takeNumbers ? aPolygoneInfo->IsElemNum() : eFAUX;
199               
200               TInt aNbElem = aPolygoneInfo->GetNbElem();
201               for(TInt iElem = 0; iElem < aNbElem; iElem++){
202                 MED::TCConnSlice aConnSlice = aPolygoneInfo->GetConnSlice(iElem);
203                 TInt aNbConn = aPolygoneInfo->GetNbConn(iElem);
204                 TNodeIds aNodeIds(aNbConn);
205 #ifdef _EDF_NODE_IDS_
206                 if(anIsNodeNum)
207                   for(TInt iConn = 0; iConn < aNbConn; iConn++)
208                     aNodeIds[iConn] = aNodeInfo->GetElemNum(aConnSlice[iConn] - 1);
209                 else
210                   for(TInt iConn = 0; iConn < aNbConn; iConn++)
211                     aNodeIds[iConn] = aConnSlice[iConn];
212 #else
213                 for(TInt iConn = 0; iConn < aNbConn; iConn++)
214                   aNodeIds[iConn] = aConnSlice[iConn];
215 #endif
216                 bool isRenum = false;
217                 SMDS_MeshElement* anElement = NULL;
218                 TInt aFamNum = aPolygoneInfo->GetFamNum(iElem);
219
220 #ifndef _DEXCEPT_
221                 try{
222 #endif
223                   if(anIsElemNum){
224                     TInt anElemId = aPolygoneInfo->GetElemNum(iElem);
225                     anElement = myMesh->AddPolygonalFaceWithID(aNodeIds,anElemId);
226                   }
227                   if(!anElement){
228                     std::vector<const SMDS_MeshNode*> aNodes(aNbConn);
229                     for(TInt iConn = 0; iConn < aNbConn; iConn++)
230                       aNodes[iConn] = FindNode(myMesh,aNodeIds[iConn]);
231                     anElement = myMesh->AddPolygonalFace(aNodes);
232                     isRenum = anIsElemNum;
233                   }
234 #ifndef _DEXCEPT_
235                 }catch(const std::exception& exc){
236                   aResult = DRS_FAIL;
237                 }catch (...){
238                   aResult = DRS_FAIL;
239                 }
240 #endif
241                 if(!anElement){
242                   aResult = DRS_WARN_SKIP_ELEM;
243                 }else{
244                   if(isRenum){
245                     anIsElemNum = eFAUX;
246                     takeNumbers = false;
247                     if(aResult < DRS_WARN_RENUMBER)
248                       aResult = DRS_WARN_RENUMBER;
249                   }
250                   if ( checkFamilyID ( aFamily, aFamNum ))
251                   {
252                     // Save reference to this element from its family
253                     aFamily->AddElement(anElement);
254                     aFamily->SetType(anElement->GetType());
255                   }
256                 }
257               }
258               break;
259             }
260             case ePOLYEDRE: {
261               PPolyedreInfo aPolyedreInfo = aMed->GetPPolyedreInfo(aMeshInfo,anEntity,aGeom);
262               EBooleen anIsElemNum = takeNumbers ? aPolyedreInfo->IsElemNum() : eFAUX;
263
264               TInt aNbElem = aPolyedreInfo->GetNbElem();
265               for(TInt iElem = 0; iElem < aNbElem; iElem++){
266                 MED::TCConnSliceArr aConnSliceArr = aPolyedreInfo->GetConnSliceArr(iElem);
267                 TInt aNbFaces = aConnSliceArr.size();
268                 typedef MED::TVector<int> TQuantities;
269                 TQuantities aQuantities(aNbFaces);
270                 TInt aNbNodes = aPolyedreInfo->GetNbNodes(iElem);
271                 TNodeIds aNodeIds(aNbNodes);
272                 for(TInt iFace = 0, iNode = 0; iFace < aNbFaces; iFace++){
273                   MED::TCConnSlice aConnSlice = aConnSliceArr[iFace];
274                   TInt aNbConn = aConnSlice.size();
275                   aQuantities[iFace] = aNbConn;
276 #ifdef _EDF_NODE_IDS_
277                   if(anIsNodeNum)
278                     for(TInt iConn = 0; iConn < aNbConn; iConn++)
279                       aNodeIds[iNode++] = aNodeInfo->GetElemNum(aConnSlice[iConn] - 1);
280                   else
281                     for(TInt iConn = 0; iConn < aNbConn; iConn++)
282                       aNodeIds[iNode++] = aConnSlice[iConn];
283 #else
284                   for(TInt iConn = 0; iConn < aNbConn; iConn++)
285                     aNodeIds[iNode++] = aConnSlice[iConn];
286 #endif          
287                 }
288
289                 bool isRenum = false;
290                 SMDS_MeshElement* anElement = NULL;
291                 TInt aFamNum = aPolyedreInfo->GetFamNum(iElem);
292                 
293 #ifndef _DEXCEPT_
294                 try{
295 #endif
296                   if(anIsElemNum){
297                     TInt anElemId = aPolyedreInfo->GetElemNum(iElem);
298                     anElement = myMesh->AddPolyhedralVolumeWithID(aNodeIds,aQuantities,anElemId);
299                   }
300                   if(!anElement){
301                     std::vector<const SMDS_MeshNode*> aNodes(aNbNodes);
302                     for(TInt iConn = 0; iConn < aNbNodes; iConn++)
303                       aNodes[iConn] = FindNode(myMesh,aNodeIds[iConn]);
304                     anElement = myMesh->AddPolyhedralVolume(aNodes,aQuantities);
305                     isRenum = anIsElemNum;
306                   }
307 #ifndef _DEXCEPT_
308                 }catch(const std::exception& exc){
309                   aResult = DRS_FAIL;
310                 }catch(...){
311                   aResult = DRS_FAIL;
312                 }
313 #endif          
314                 if(!anElement){
315                   aResult = DRS_WARN_SKIP_ELEM;
316                 }else{
317                   if(isRenum){
318                     anIsElemNum = eFAUX;
319                     takeNumbers = false;
320                     if (aResult < DRS_WARN_RENUMBER)
321                       aResult = DRS_WARN_RENUMBER;
322                   }
323                   if ( checkFamilyID ( aFamily, aFamNum )) {
324                     // Save reference to this element from its family
325                     aFamily->AddElement(anElement);
326                     aFamily->SetType(anElement->GetType());
327                   }
328                 }
329               }
330               break;
331             }
332             default: {
333               PCellInfo aCellInfo = aMed->GetPCellInfo(aMeshInfo,anEntity,aGeom);
334               EBooleen anIsElemNum = takeNumbers ? aCellInfo->IsElemNum() : eFAUX;
335               TInt aNbElems = aCellInfo->GetNbElem();
336               if(MYDEBUG) MESSAGE("Perform - anEntity = "<<anEntity<<"; anIsElemNum = "<<anIsElemNum);
337               if(MYDEBUG) MESSAGE("Perform - aGeom = "<<aGeom<<"; aNbElems = "<<aNbElems);
338
339               for(int iElem = 0; iElem < aNbElems; iElem++){
340                 TInt aNbNodes = -1;
341                 switch(aGeom){
342                 case eSEG2:    aNbNodes = 2;  break;
343                 case eSEG3:    aNbNodes = 3;  break;
344                 case eTRIA3:   aNbNodes = 3;  break;
345                 case eTRIA6:   aNbNodes = 6;  break;
346                 case eQUAD4:   aNbNodes = 4;  break;
347                 case eQUAD8:   aNbNodes = 8;  break;
348                 case eTETRA4:  aNbNodes = 4;  break;
349                 case eTETRA10: aNbNodes = 10; break;
350                 case ePYRA5:   aNbNodes = 5;  break;
351                 case ePYRA13:  aNbNodes = 13; break;
352                 case ePENTA6:  aNbNodes = 6;  break;
353                 case ePENTA15: aNbNodes = 15; break;
354                 case eHEXA8:   aNbNodes = 8;  break;
355                 case eHEXA20:  aNbNodes = 20; break;
356                 case ePOINT1:  aNbNodes = 1;  break;
357                 default:;
358                 }
359                 std::vector<TInt> aNodeIds(aNbNodes);
360                 bool anIsValidConnect = false;
361                 TCConnSlice aConnSlice = aCellInfo->GetConnSlice(iElem);
362 #ifndef _DEXCEPT_
363                 try{
364 #endif
365 #ifdef _EDF_NODE_IDS_
366                   if(anIsNodeNum)
367                     for(int iNode = 0; iNode < aNbNodes; iNode++)
368                       aNodeIds[iNode] = aNodeInfo->GetElemNum(aConnSlice[iNode] - 1);
369                   else
370                     for(int iNode = 0; iNode < aNbNodes; iNode++)
371                       aNodeIds[iNode] = aConnSlice[iNode];
372 #else
373                   for(int iNode = 0; iNode < aNbNodes; iNode++)
374                     aNodeIds[iNode] = aConnSlice[iNode];
375 #endif
376                   anIsValidConnect = true;
377 #ifndef _DEXCEPT_
378                 }catch(const std::exception& exc){
379                   //INFOS("Follow exception was cought:\n\t"<<exc.what());
380                   aResult = DRS_FAIL;
381                 }catch(...){
382                   //INFOS("Unknown exception was cought !!!");
383                   aResult = DRS_FAIL;
384                 }
385 #endif          
386                 if(!anIsValidConnect)
387                   continue;
388
389                 bool isRenum = false;
390                 const SMDS_MeshElement* anElement = NULL;
391                 TInt aFamNum = aCellInfo->GetFamNum(iElem);
392 #ifndef _DEXCEPT_
393                 try{
394 #endif
395                   //MESSAGE("Try to create element # " << iElem << " with id = "
396                   //        << aCellInfo->GetElemNum(iElem));
397                   switch(aGeom) {
398                   case ePOINT1:
399                     //anElement = FindNode(myMesh,aNodeIds[0]);
400                     if(anIsElemNum)
401                       anElement = myMesh->Add0DElementWithID
402                         (aNodeIds[0], aCellInfo->GetElemNum(iElem));
403                     if (!anElement) {
404                       anElement = myMesh->Add0DElement(FindNode(myMesh,aNodeIds[0]));
405                       isRenum = anIsElemNum;
406                     }
407                     break;
408                   case eSEG2:
409                     if(anIsElemNum)
410                       anElement = myMesh->AddEdgeWithID(aNodeIds[0],
411                                                         aNodeIds[1],
412                                                         aCellInfo->GetElemNum(iElem));
413                     if (!anElement) {
414                       anElement = myMesh->AddEdge(FindNode(myMesh,aNodeIds[0]),
415                                                   FindNode(myMesh,aNodeIds[1]));
416                       isRenum = anIsElemNum;
417                     }
418                     break;
419                   case eSEG3:
420                     if(anIsElemNum)
421                       anElement = myMesh->AddEdgeWithID(aNodeIds[0],
422                                                         aNodeIds[1],
423                                                         aNodeIds[2],
424                                                         aCellInfo->GetElemNum(iElem));
425                     if (!anElement) {
426                       anElement = myMesh->AddEdge(FindNode(myMesh,aNodeIds[0]),
427                                                   FindNode(myMesh,aNodeIds[1]),
428                                                   FindNode(myMesh,aNodeIds[2]));
429                       isRenum = anIsElemNum;
430                     }
431                     break;
432                   case eTRIA3:
433                     aNbNodes = 3;
434                     if(anIsElemNum)
435                       anElement = myMesh->AddFaceWithID(aNodeIds[0],
436                                                         aNodeIds[1],
437                                                         aNodeIds[2],
438                                                         aCellInfo->GetElemNum(iElem));
439                     if (!anElement) {
440                       anElement = myMesh->AddFace(FindNode(myMesh,aNodeIds[0]),
441                                                   FindNode(myMesh,aNodeIds[1]),
442                                                   FindNode(myMesh,aNodeIds[2]));
443                       isRenum = anIsElemNum;
444                     }
445                     break;
446                   case eTRIA6:
447                     aNbNodes = 6;
448                     if(anIsElemNum)
449                       anElement = myMesh->AddFaceWithID(aNodeIds[0], aNodeIds[1],
450                                                         aNodeIds[2], aNodeIds[3],
451                                                         aNodeIds[4], aNodeIds[5],
452                                                         aCellInfo->GetElemNum(iElem));
453                     if (!anElement) {
454                       anElement = myMesh->AddFace(FindNode(myMesh,aNodeIds[0]),
455                                                   FindNode(myMesh,aNodeIds[1]),
456                                                   FindNode(myMesh,aNodeIds[2]),
457                                                   FindNode(myMesh,aNodeIds[3]),
458                                                   FindNode(myMesh,aNodeIds[4]),
459                                                   FindNode(myMesh,aNodeIds[5]));
460                       isRenum = anIsElemNum;
461                     }
462                     break;
463                   case eQUAD4:
464                     aNbNodes = 4;
465                     if(anIsElemNum)
466                       anElement = myMesh->AddFaceWithID(aNodeIds[0], aNodeIds[1],
467                                                         aNodeIds[2], aNodeIds[3],
468                                                         aCellInfo->GetElemNum(iElem));
469                     if (!anElement) {
470                       anElement = myMesh->AddFace(FindNode(myMesh,aNodeIds[0]),
471                                                   FindNode(myMesh,aNodeIds[1]),
472                                                   FindNode(myMesh,aNodeIds[2]),
473                                                   FindNode(myMesh,aNodeIds[3]));
474                       isRenum = anIsElemNum;
475                     }
476                     break;
477                   case eQUAD8:
478                     aNbNodes = 8;
479                     if(anIsElemNum)
480                       anElement = myMesh->AddFaceWithID(aNodeIds[0], aNodeIds[1],
481                                                         aNodeIds[2], aNodeIds[3],
482                                                         aNodeIds[4], aNodeIds[5],
483                                                         aNodeIds[6], aNodeIds[7],
484                                                         aCellInfo->GetElemNum(iElem));
485                     if (!anElement) {
486                       anElement = myMesh->AddFace(FindNode(myMesh,aNodeIds[0]),
487                                                   FindNode(myMesh,aNodeIds[1]),
488                                                   FindNode(myMesh,aNodeIds[2]),
489                                                   FindNode(myMesh,aNodeIds[3]),
490                                                   FindNode(myMesh,aNodeIds[4]),
491                                                   FindNode(myMesh,aNodeIds[5]),
492                                                   FindNode(myMesh,aNodeIds[6]),
493                                                   FindNode(myMesh,aNodeIds[7]));
494                       isRenum = anIsElemNum;
495                     }
496                     break;
497                   case eTETRA4:
498                     aNbNodes = 4;
499                     if(anIsElemNum)
500                       anElement = myMesh->AddVolumeWithID(aNodeIds[0], aNodeIds[1],
501                                                           aNodeIds[2], aNodeIds[3],
502                                                           aCellInfo->GetElemNum(iElem));
503                     if (!anElement) {
504                       anElement = myMesh->AddVolume(FindNode(myMesh,aNodeIds[0]),
505                                                     FindNode(myMesh,aNodeIds[1]),
506                                                     FindNode(myMesh,aNodeIds[2]),
507                                                     FindNode(myMesh,aNodeIds[3]));
508                       isRenum = anIsElemNum;
509                     }
510                     break;
511                   case eTETRA10:
512                     aNbNodes = 10;
513                     if(anIsElemNum)
514                       anElement = myMesh->AddVolumeWithID(aNodeIds[0], aNodeIds[1],
515                                                           aNodeIds[2], aNodeIds[3],
516                                                           aNodeIds[4], aNodeIds[5],
517                                                           aNodeIds[6], aNodeIds[7],
518                                                           aNodeIds[8], aNodeIds[9],
519                                                           aCellInfo->GetElemNum(iElem));
520                     if (!anElement) {
521                       anElement = myMesh->AddVolume(FindNode(myMesh,aNodeIds[0]),
522                                                     FindNode(myMesh,aNodeIds[1]),
523                                                     FindNode(myMesh,aNodeIds[2]),
524                                                     FindNode(myMesh,aNodeIds[3]),
525                                                     FindNode(myMesh,aNodeIds[4]),
526                                                     FindNode(myMesh,aNodeIds[5]),
527                                                     FindNode(myMesh,aNodeIds[6]),
528                                                     FindNode(myMesh,aNodeIds[7]),
529                                                     FindNode(myMesh,aNodeIds[8]),
530                                                     FindNode(myMesh,aNodeIds[9]));
531                       isRenum = anIsElemNum;
532                     }
533                     break;
534                   case ePYRA5:
535                     aNbNodes = 5;
536                     // There is some differnce between SMDS and MED
537                     if(anIsElemNum)
538                       anElement = myMesh->AddVolumeWithID(aNodeIds[0], aNodeIds[1],
539                                                           aNodeIds[2], aNodeIds[3],
540                                                           aNodeIds[4],
541                                                           aCellInfo->GetElemNum(iElem));
542                     if (!anElement) {
543                       anElement = myMesh->AddVolume(FindNode(myMesh,aNodeIds[0]),
544                                                     FindNode(myMesh,aNodeIds[1]),
545                                                     FindNode(myMesh,aNodeIds[2]),
546                                                     FindNode(myMesh,aNodeIds[3]),
547                                                     FindNode(myMesh,aNodeIds[4]));
548                       isRenum = anIsElemNum;
549                     }
550                     break;
551                   case ePYRA13:
552                     aNbNodes = 13;
553                     // There is some differnce between SMDS and MED
554                     if(anIsElemNum)
555                       anElement = myMesh->AddVolumeWithID(aNodeIds[0], aNodeIds[1],
556                                                           aNodeIds[2], aNodeIds[3],
557                                                           aNodeIds[4], aNodeIds[5],
558                                                           aNodeIds[6], aNodeIds[7],
559                                                           aNodeIds[8], aNodeIds[9],
560                                                           aNodeIds[10], aNodeIds[11],
561                                                           aNodeIds[12],
562                                                           aCellInfo->GetElemNum(iElem));
563                     if (!anElement) {
564                       anElement = myMesh->AddVolume(FindNode(myMesh,aNodeIds[0]),
565                                                     FindNode(myMesh,aNodeIds[1]),
566                                                     FindNode(myMesh,aNodeIds[2]),
567                                                     FindNode(myMesh,aNodeIds[3]),
568                                                     FindNode(myMesh,aNodeIds[4]),
569                                                     FindNode(myMesh,aNodeIds[5]),
570                                                     FindNode(myMesh,aNodeIds[6]),
571                                                     FindNode(myMesh,aNodeIds[7]),
572                                                     FindNode(myMesh,aNodeIds[8]),
573                                                     FindNode(myMesh,aNodeIds[9]),
574                                                     FindNode(myMesh,aNodeIds[10]),
575                                                     FindNode(myMesh,aNodeIds[11]),
576                                                     FindNode(myMesh,aNodeIds[12]));
577                       isRenum = anIsElemNum;
578                     }
579                     break;
580                   case ePENTA6:
581                     aNbNodes = 6;
582                     if(anIsElemNum)
583                       anElement = myMesh->AddVolumeWithID(aNodeIds[0],
584                                                           aNodeIds[1],
585                                                           aNodeIds[2],
586                                                           aNodeIds[3],
587                                                           aNodeIds[4],
588                                                           aNodeIds[5],
589                                                           aCellInfo->GetElemNum(iElem));
590                     if (!anElement) {
591                       anElement = myMesh->AddVolume(FindNode(myMesh,aNodeIds[0]),
592                                                     FindNode(myMesh,aNodeIds[1]),
593                                                     FindNode(myMesh,aNodeIds[2]),
594                                                     FindNode(myMesh,aNodeIds[3]),
595                                                     FindNode(myMesh,aNodeIds[4]),
596                                                     FindNode(myMesh,aNodeIds[5]));
597                       isRenum = anIsElemNum;
598                     }
599                     break;
600                   case ePENTA15:
601                     aNbNodes = 15;
602                     if(anIsElemNum)
603                       anElement = myMesh->AddVolumeWithID(aNodeIds[0], aNodeIds[1],
604                                                           aNodeIds[2], aNodeIds[3],
605                                                           aNodeIds[4], aNodeIds[5],
606                                                           aNodeIds[6], aNodeIds[7],
607                                                           aNodeIds[8], aNodeIds[9],
608                                                           aNodeIds[10], aNodeIds[11],
609                                                           aNodeIds[12], aNodeIds[13],
610                                                           aNodeIds[14],
611                                                           aCellInfo->GetElemNum(iElem));
612                     if (!anElement) {
613                       anElement = myMesh->AddVolume(FindNode(myMesh,aNodeIds[0]),
614                                                     FindNode(myMesh,aNodeIds[1]),
615                                                     FindNode(myMesh,aNodeIds[2]),
616                                                     FindNode(myMesh,aNodeIds[3]),
617                                                   FindNode(myMesh,aNodeIds[4]),
618                                                     FindNode(myMesh,aNodeIds[5]),
619                                                     FindNode(myMesh,aNodeIds[6]),
620                                                     FindNode(myMesh,aNodeIds[7]),
621                                                     FindNode(myMesh,aNodeIds[8]),
622                                                     FindNode(myMesh,aNodeIds[9]),
623                                                     FindNode(myMesh,aNodeIds[10]),
624                                                     FindNode(myMesh,aNodeIds[11]),
625                                                     FindNode(myMesh,aNodeIds[12]),
626                                                     FindNode(myMesh,aNodeIds[13]),
627                                                     FindNode(myMesh,aNodeIds[14]));
628                       isRenum = anIsElemNum;
629                     }
630                     break;
631                   case eHEXA8:
632                     aNbNodes = 8;
633                     if(anIsElemNum)
634                       anElement = myMesh->AddVolumeWithID(aNodeIds[0],
635                                                           aNodeIds[1],
636                                                           aNodeIds[2],
637                                                           aNodeIds[3],
638                                                           aNodeIds[4],
639                                                           aNodeIds[5],
640                                                           aNodeIds[6],
641                                                           aNodeIds[7],
642                                                           aCellInfo->GetElemNum(iElem));
643                     if (!anElement) {
644                       anElement = myMesh->AddVolume(FindNode(myMesh,aNodeIds[0]),
645                                                     FindNode(myMesh,aNodeIds[1]),
646                                                     FindNode(myMesh,aNodeIds[2]),
647                                                     FindNode(myMesh,aNodeIds[3]),
648                                                     FindNode(myMesh,aNodeIds[4]),
649                                                     FindNode(myMesh,aNodeIds[5]),
650                                                     FindNode(myMesh,aNodeIds[6]),
651                                                     FindNode(myMesh,aNodeIds[7]));
652                       isRenum = anIsElemNum;
653                     }
654                     break;
655                   case eHEXA20:
656                     aNbNodes = 20;
657                     if(anIsElemNum)
658                       anElement = myMesh->AddVolumeWithID(aNodeIds[0], aNodeIds[1],
659                                                           aNodeIds[2], aNodeIds[3],
660                                                           aNodeIds[4], aNodeIds[5],
661                                                           aNodeIds[6], aNodeIds[7],
662                                                           aNodeIds[8], aNodeIds[9],
663                                                           aNodeIds[10], aNodeIds[11],
664                                                           aNodeIds[12], aNodeIds[13],
665                                                           aNodeIds[14], aNodeIds[15],
666                                                           aNodeIds[16], aNodeIds[17],
667                                                           aNodeIds[18], aNodeIds[19],
668                                                           aCellInfo->GetElemNum(iElem));
669                     if (!anElement) {
670                       anElement = myMesh->AddVolume(FindNode(myMesh,aNodeIds[0]),
671                                                     FindNode(myMesh,aNodeIds[1]),
672                                                     FindNode(myMesh,aNodeIds[2]),
673                                                     FindNode(myMesh,aNodeIds[3]),
674                                                     FindNode(myMesh,aNodeIds[4]),
675                                                     FindNode(myMesh,aNodeIds[5]),
676                                                     FindNode(myMesh,aNodeIds[6]),
677                                                     FindNode(myMesh,aNodeIds[7]),
678                                                     FindNode(myMesh,aNodeIds[8]),
679                                                     FindNode(myMesh,aNodeIds[9]),
680                                                     FindNode(myMesh,aNodeIds[10]),
681                                                     FindNode(myMesh,aNodeIds[11]),
682                                                     FindNode(myMesh,aNodeIds[12]),
683                                                     FindNode(myMesh,aNodeIds[13]),
684                                                     FindNode(myMesh,aNodeIds[14]),
685                                                     FindNode(myMesh,aNodeIds[15]),
686                                                     FindNode(myMesh,aNodeIds[16]),
687                                                     FindNode(myMesh,aNodeIds[17]),
688                                                     FindNode(myMesh,aNodeIds[18]),
689                                                     FindNode(myMesh,aNodeIds[19]));
690                       isRenum = anIsElemNum;
691                     }
692                     break;
693                   }
694
695 #ifndef _DEXCEPT_
696                 }catch(const std::exception& exc){
697                   //INFOS("Follow exception was cought:\n\t"<<exc.what());
698                   aResult = DRS_FAIL;
699                 }catch(...){
700                   //INFOS("Unknown exception was cought !!!");
701                   aResult = DRS_FAIL;
702                 }
703 #endif          
704                 if (!anElement) {
705                   aResult = DRS_WARN_SKIP_ELEM;
706                 }
707                 else {
708                   if (isRenum) {
709                     anIsElemNum = eFAUX;
710                     takeNumbers = false;
711                     if (aResult < DRS_WARN_RENUMBER)
712                       aResult = DRS_WARN_RENUMBER;
713                   }
714                   if ( checkFamilyID ( aFamily, aFamNum )) {
715                     // Save reference to this element from its family
716                     myFamilies[aFamNum]->AddElement(anElement);
717                     myFamilies[aFamNum]->SetType(anElement->GetType());
718                   }
719                 }
720               }
721             }}
722           }
723         }
724       }
725     }
726 #ifndef _DEXCEPT_
727   }catch(const std::exception& exc){
728     INFOS("Follow exception was cought:\n\t"<<exc.what());
729     aResult = DRS_FAIL;
730   }catch(...){
731     INFOS("Unknown exception was cought !!!");
732     aResult = DRS_FAIL;
733   }
734 #endif
735   if(MYDEBUG) MESSAGE("Perform - aResult status = "<<aResult);
736   return aResult;
737 }
738
739 std::list<std::string> DriverMED_R_SMESHDS_Mesh::GetMeshNames(Status& theStatus)
740 {
741   std::list<std::string> aMeshNames;
742
743   try {
744     if(MYDEBUG) MESSAGE("GetMeshNames - myFile : " << myFile);
745     theStatus = DRS_OK;
746     PWrapper aMed = CrWrapper(myFile);
747
748     if (TInt aNbMeshes = aMed->GetNbMeshes()) {
749       for (int iMesh = 0; iMesh < aNbMeshes; iMesh++) {
750         // Reading the MED mesh
751         //---------------------
752         PMeshInfo aMeshInfo = aMed->GetPMeshInfo(iMesh+1);
753         aMeshNames.push_back(aMeshInfo->GetName());
754       }
755     }
756   }catch(const std::exception& exc){
757     INFOS("Follow exception was cought:\n\t"<<exc.what());
758     theStatus = DRS_FAIL;
759   }catch(...){
760     INFOS("Unknown exception was cought !!!");
761     theStatus = DRS_FAIL;
762   }
763
764   return aMeshNames;
765 }
766
767 std::list<TNameAndType> DriverMED_R_SMESHDS_Mesh::GetGroupNamesAndTypes()
768 {
769   std::list<TNameAndType> aResult;
770   std::set<TNameAndType> aResGroupNames;
771
772   std::map<int, DriverMED_FamilyPtr>::iterator aFamsIter = myFamilies.begin();
773   for (; aFamsIter != myFamilies.end(); aFamsIter++)
774   {
775     DriverMED_FamilyPtr aFamily = (*aFamsIter).second;
776     const MED::TStringSet& aGroupNames = aFamily->GetGroupNames();
777     std::set<std::string>::const_iterator aGrNamesIter = aGroupNames.begin();
778     for (; aGrNamesIter != aGroupNames.end(); aGrNamesIter++)
779     {
780       TNameAndType aNameAndType = make_pair( *aGrNamesIter, aFamily->GetType() );
781       // Check, if this is a Group or SubMesh name
782 //if (aName.substr(0, 5) == string("Group")) {
783         if ( aResGroupNames.insert( aNameAndType ).second ) {
784           aResult.push_back( aNameAndType );
785         }
786 //    }
787     }
788   }
789
790   return aResult;
791 }
792
793 void DriverMED_R_SMESHDS_Mesh::GetGroup(SMESHDS_Group* theGroup)
794 {
795   std::string aGroupName (theGroup->GetStoreName());
796   if(MYDEBUG) MESSAGE("Get Group " << aGroupName);
797
798   std::map<int, DriverMED_FamilyPtr>::iterator aFamsIter = myFamilies.begin();
799   for (; aFamsIter != myFamilies.end(); aFamsIter++)
800   {
801     DriverMED_FamilyPtr aFamily = (*aFamsIter).second;
802     if (aFamily->GetType() == theGroup->GetType() && aFamily->MemberOf(aGroupName))
803     {
804       const std::set<const SMDS_MeshElement *>& anElements = aFamily->GetElements();
805       std::set<const SMDS_MeshElement *>::const_iterator anElemsIter = anElements.begin();
806       const SMDS_MeshElement * element = 0;
807       for (; anElemsIter != anElements.end(); anElemsIter++)
808       {
809         element = *anElemsIter;
810         theGroup->SMDSGroup().Add(element);
811         int aGroupAttrVal = aFamily->GetGroupAttributVal();
812         if( aGroupAttrVal != 0)
813           theGroup->SetColorGroup(aGroupAttrVal);
814       }
815       if ( element )
816         theGroup->SetType( theGroup->SMDSGroup().GetType() );
817     }
818   }
819 }
820
821 void DriverMED_R_SMESHDS_Mesh::GetSubMesh (SMESHDS_SubMesh* theSubMesh,
822                                            const int theId)
823 {
824   char submeshGrpName[ 30 ];
825   sprintf( submeshGrpName, "SubMesh %d", theId );
826   std::string aName (submeshGrpName);
827   std::map<int, DriverMED_FamilyPtr>::iterator aFamsIter = myFamilies.begin();
828   for (; aFamsIter != myFamilies.end(); aFamsIter++)
829   {
830     DriverMED_FamilyPtr aFamily = (*aFamsIter).second;
831     if (aFamily->MemberOf(aName))
832     {
833       const std::set<const SMDS_MeshElement *>& anElements = aFamily->GetElements();
834       std::set<const SMDS_MeshElement *>::const_iterator anElemsIter = anElements.begin();
835       if (aFamily->GetType() == SMDSAbs_Node)
836       {
837         for (; anElemsIter != anElements.end(); anElemsIter++)
838         {
839           const SMDS_MeshNode* node = static_cast<const SMDS_MeshNode*>(*anElemsIter);
840           theSubMesh->AddNode(node);
841         }
842       }
843       else
844       {
845         for (; anElemsIter != anElements.end(); anElemsIter++)
846         {
847           theSubMesh->AddElement(*anElemsIter);
848         }
849       }
850     }
851   }
852 }
853
854 void DriverMED_R_SMESHDS_Mesh::CreateAllSubMeshes ()
855 {
856   std::map<int, DriverMED_FamilyPtr>::iterator aFamsIter = myFamilies.begin();
857   for (; aFamsIter != myFamilies.end(); aFamsIter++)
858   {
859     DriverMED_FamilyPtr aFamily = (*aFamsIter).second;
860     MED::TStringSet aGroupNames = aFamily->GetGroupNames();
861     std::set<std::string>::iterator aGrNamesIter = aGroupNames.begin();
862     for (; aGrNamesIter != aGroupNames.end(); aGrNamesIter++)
863     {
864       std::string aName = *aGrNamesIter;
865       // Check, if this is a Group or SubMesh name
866       if (aName.substr(0, 7) == std::string("SubMesh"))
867       {
868         int Id = atoi(std::string(aName).substr(7).c_str());
869         std::set<const SMDS_MeshElement *> anElements = aFamily->GetElements();
870         std::set<const SMDS_MeshElement *>::iterator anElemsIter = anElements.begin();
871         if (aFamily->GetType() == SMDSAbs_Node)
872         {
873           for (; anElemsIter != anElements.end(); anElemsIter++)
874           {
875             SMDS_MeshNode* node = const_cast<SMDS_MeshNode*>
876               ( static_cast<const SMDS_MeshNode*>( *anElemsIter ));
877             // find out a shape type
878             TopoDS_Shape aShape = myMesh->IndexToShape( Id );
879             int aShapeType = ( aShape.IsNull() ? -1 : aShape.ShapeType() );
880             switch ( aShapeType ) {
881             case TopAbs_FACE:
882               myMesh->SetNodeOnFace(node, Id); break;
883             case TopAbs_EDGE:
884               myMesh->SetNodeOnEdge(node, Id); break;
885             case TopAbs_VERTEX:
886               myMesh->SetNodeOnVertex(node, Id); break;
887             default:
888               myMesh->SetNodeInVolume(node, Id);
889             }
890           }
891         }
892         else
893         {
894           for (; anElemsIter != anElements.end(); anElemsIter++)
895           {
896             myMesh->SetMeshElementOnShape(*anElemsIter, Id);
897           }
898         }
899       }
900     }
901   }
902 }
903 /*!
904  * \brief Ensure aFamily to have required ID
905  * \param aFamily - a family to check and update
906  * \param anID - an ID aFamily should have
907  * \retval bool  - true if successful
908  */
909 bool DriverMED_R_SMESHDS_Mesh::checkFamilyID(DriverMED_FamilyPtr & aFamily, int anID) const
910 {
911   if ( !aFamily || aFamily->GetId() != anID ) {
912     std::map<int, DriverMED_FamilyPtr>::const_iterator i_fam = myFamilies.find(anID);
913     if ( i_fam == myFamilies.end() )
914       return false;
915     aFamily = i_fam->second;
916   }
917   return ( aFamily->GetId() == anID );
918 }
919
920
921 /*! \brief Reading the structured mesh and convert to non structured (by filling of smesh structure for non structured mesh)
922  * \param theWrapper  - PWrapper const pointer
923  * \param theMeshInfo - PMeshInfo const pointer
924  * \return TRUE, if successfully. Else FALSE
925  */
926 bool DriverMED_R_SMESHDS_Mesh::buildMeshGrille(const MED::PWrapper& theWrapper,
927                                                const MED::PMeshInfo& theMeshInfo)
928 {
929   bool res = true;
930
931   MED::PGrilleInfo aGrilleInfo = theWrapper->GetPGrilleInfo(theMeshInfo);
932   MED::TInt aNbNodes = aGrilleInfo->GetNbNodes();
933   MED::TInt aNbCells = aGrilleInfo->GetNbCells();
934   MED::TInt aMeshDim = theMeshInfo->GetDim();
935   DriverMED_FamilyPtr aFamily;
936   for(MED::TInt iNode=0;iNode < aNbNodes; iNode++){
937     double aCoords[3] = {0.0, 0.0, 0.0};
938     const SMDS_MeshNode* aNode;
939     MED::TNodeCoord aMEDNodeCoord = aGrilleInfo->GetCoord(iNode);
940     for(MED::TInt iDim=0;iDim<aMeshDim;iDim++)
941       aCoords[(int)iDim] = aMEDNodeCoord[(int)iDim];
942     aNode = myMesh->AddNodeWithID(aCoords[0],aCoords[1],aCoords[2],(int)iNode);
943
944     if((aGrilleInfo->myFamNumNode).size() > 0){
945       TInt aFamNum = aGrilleInfo->GetFamNumNode(iNode);
946       if ( checkFamilyID ( aFamily, aFamNum ))
947         {
948           aFamily->AddElement(aNode);
949           aFamily->SetType(SMDSAbs_Node);
950         }
951     }
952     
953   }
954
955   SMDS_MeshElement* anElement = NULL;
956   MED::TIntVector aNodeIds;
957   for(MED::TInt iCell=0;iCell < aNbCells; iCell++){
958     aNodeIds = aGrilleInfo->GetConn(iCell);
959     switch(aGrilleInfo->GetGeom()){
960     case MED::eSEG2:
961       if(aNodeIds.size() != 2){
962         res = false;
963         EXCEPTION(std::runtime_error,"buildMeshGrille Error. Incorrect size of ids 2!="<<aNodeIds.size());
964       }
965       anElement = myMesh->AddEdgeWithID(aNodeIds[0],
966                                         aNodeIds[1],
967                                         iCell);
968       break;
969     case MED::eQUAD4:
970       if(aNodeIds.size() != 4){
971         res = false;
972         EXCEPTION(std::runtime_error,"buildMeshGrille Error. Incorrect size of ids 4!="<<aNodeIds.size());
973       }
974       anElement = myMesh->AddFaceWithID(aNodeIds[0],
975                                         aNodeIds[2],
976                                         aNodeIds[3],
977                                         aNodeIds[1],
978                                         iCell);
979       break;
980     case MED::eHEXA8:
981       if(aNodeIds.size() != 8){
982         res = false;
983         EXCEPTION(std::runtime_error,"buildMeshGrille Error. Incorrect size of ids 8!="<<aNodeIds.size());
984       }
985       anElement = myMesh->AddVolumeWithID(aNodeIds[0],
986                                           aNodeIds[2],
987                                           aNodeIds[3],
988                                           aNodeIds[1],
989                                           aNodeIds[4],
990                                           aNodeIds[6],
991                                           aNodeIds[7],
992                                           aNodeIds[5],
993                                           iCell);
994       break;
995     default:
996       break;
997     }
998     
999     if((aGrilleInfo->myFamNum).size() > 0){
1000       TInt aFamNum = aGrilleInfo->GetFamNum(iCell);
1001       if ( checkFamilyID ( aFamily, aFamNum )){
1002         aFamily->AddElement(anElement);
1003         aFamily->SetType(anElement->GetType());
1004       }
1005     }
1006   }
1007
1008   return res;
1009 }