1 // SMESH DriverMED : driver to read and write 'med' files
3 // Copyright (C) 2003 OPEN CASCADE, EADS/CCR, LIP6, CEA/DEN,
4 // CEDRAT, EDF R&D, LEG, PRINCIPIA R&D, BUREAU VERITAS
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.
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.
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
20 // See http://www.opencascade.org/SALOME/ or email : webmaster.salome@opencascade.org
24 // File : DriverMED_R_SMESHDS_Mesh.cxx
27 #include "DriverMED_R_SMESHDS_Mesh.h"
28 #include "DriverMED_R_SMDS_Mesh.h"
29 #include "SMESHDS_Mesh.hxx"
30 #include "utilities.h"
32 #include "DriverMED_Family.h"
34 #include "SMESHDS_Group.hxx"
36 #include "MED_Factory.hxx"
37 #include "MED_CoordUtils.hxx"
38 #include "MED_Utilities.hxx"
43 static int MYDEBUG = 0;
45 static int MYDEBUG = 0;
48 #define _EDF_NODE_IDS_
53 DriverMED_R_SMESHDS_Mesh
54 ::SetMeshName(string theMeshName)
56 myMeshName = theMeshName;
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(runtime_error,"SMDS_Mesh::FindNode - cannot find a SMDS_MeshNode for ID = "<<theId);
68 DriverMED_R_SMESHDS_Mesh
71 Status aResult = DRS_FAIL;
74 if(MYDEBUG) MESSAGE("Perform - myFile : "<<myFile);
75 PWrapper aMed = CrWrapper(myFile);
78 if(TInt aNbMeshes = aMed->GetNbMeshes()){
79 for(int iMesh = 0; iMesh < aNbMeshes; iMesh++){
80 // Reading the MED mesh
81 //---------------------
82 PMeshInfo aMeshInfo = aMed->GetPMeshInfo(iMesh+1);
85 ostringstream aMeshNameStr;
86 aMeshNameStr<<myMeshId;
87 aMeshName = aMeshNameStr.str();
89 aMeshName = myMeshName;
91 if(MYDEBUG) MESSAGE("Perform - aMeshName : "<<aMeshName<<"; "<<aMeshInfo->GetName());
92 if(aMeshName != aMeshInfo->GetName()) continue;
94 //TInt aMeshDim = aMeshInfo->GetDim();
96 // Reading MED families to the temporary structure
97 //------------------------------------------------
99 TInt aNbFams = aMed->GetNbFamilies(aMeshInfo);
100 if(MYDEBUG) MESSAGE("Read " << aNbFams << " families");
101 for (TInt iFam = 0; iFam < aNbFams; iFam++) {
102 PFamilyInfo aFamilyInfo = aMed->GetPFamilyInfo(aMeshInfo,iFam+1,&anErr);
104 TInt aFamId = aFamilyInfo->GetId();
105 if(MYDEBUG) MESSAGE("Family " << aFamId << " :");
107 DriverMED_FamilyPtr aFamily (new DriverMED_Family);
109 TInt aNbGrp = aFamilyInfo->GetNbGroup();
110 if(MYDEBUG) MESSAGE("belong to " << aNbGrp << " groups");
111 for (TInt iGr = 0; iGr < aNbGrp; iGr++) {
112 string aGroupName = aFamilyInfo->GetGroupName(iGr);
113 if(MYDEBUG) MESSAGE(aGroupName);
114 aFamily->AddGroupName(aGroupName);
116 myFamilies[aFamId] = aFamily;
120 // Reading MED nodes to the corresponding SMDS structure
121 //------------------------------------------------------
122 PNodeInfo aNodeInfo = aMed->GetPNodeInfo(aMeshInfo);
124 PCoordHelper aCoordHelper = GetCoordHelper(aNodeInfo);
126 EBooleen anIsNodeNum = aNodeInfo->IsElemNum();
127 TInt aNbElems = aNodeInfo->GetNbElem();
128 if(MYDEBUG) MESSAGE("Perform - aNodeInfo->GetNbElem() = "<<aNbElems<<"; anIsNodeNum = "<<anIsNodeNum);
129 for(TInt iElem = 0; iElem < aNbElems; iElem++){
130 TCCoordSlice aCoordSlice = aNodeInfo->GetCoordSlice(iElem);
131 double aCoords[3] = {0.0, 0.0, 0.0};
132 for(TInt iDim = 0; iDim < 3; iDim++)
133 aCoords[iDim] = aCoordHelper->GetCoord(aCoordSlice,iDim);
134 const SMDS_MeshNode* aNode;
136 aNode = myMesh->AddNodeWithID
137 (aCoords[0],aCoords[1],aCoords[2],aNodeInfo->GetElemNum(iElem));
139 aNode = myMesh->AddNode
140 (aCoords[0],aCoords[1],aCoords[2]);
142 //cout<<aNode->GetID()<<": "<<aNode->X()<<", "<<aNode->Y()<<", "<<aNode->Z()<<endl;
144 // Save reference to this node from its family
145 TInt aFamNum = aNodeInfo->GetFamNum(iElem);
146 if (myFamilies.find(aFamNum) != myFamilies.end())
148 myFamilies[aFamNum]->AddElement(aNode);
149 myFamilies[aFamNum]->SetType(SMDSAbs_Node);
153 // Reading pre information about all MED cells
154 //--------------------------------------------
155 typedef std::vector<int> TNodeIds;
156 bool takeNumbers = true; // initially we trust the numbers from file
157 MED::TEntityInfo aEntityInfo = aMed->GetEntityInfo(aMeshInfo);
158 MED::TEntityInfo::iterator anEntityIter = aEntityInfo.begin();
159 for(; anEntityIter != aEntityInfo.end(); anEntityIter++){
160 const EEntiteMaillage& anEntity = anEntityIter->first;
161 if(anEntity == eNOEUD) continue;
162 // Reading MED cells to the corresponding SMDS structure
163 //------------------------------------------------------
164 const MED::TGeom2Size& aGeom2Size = anEntityIter->second;
165 MED::TGeom2Size::const_iterator aGeom2SizeIter = aGeom2Size.begin();
166 for(; aGeom2SizeIter != aGeom2Size.end(); aGeom2SizeIter++){
167 const EGeometrieElement& aGeom = aGeom2SizeIter->first;
173 PPolygoneInfo aPolygoneInfo = aMed->GetPPolygoneInfo(aMeshInfo,anEntity,aGeom);
174 EBooleen anIsElemNum = takeNumbers ? aPolygoneInfo->IsElemNum() : eFAUX;
176 TInt aNbElem = aPolygoneInfo->GetNbElem();
177 for(TInt iElem = 0; iElem < aNbElem; iElem++){
178 MED::TCConnSlice aConnSlice = aPolygoneInfo->GetConnSlice(iElem);
179 TInt aNbConn = aPolygoneInfo->GetNbConn(iElem);
180 TNodeIds aNodeIds(aNbConn);
181 #ifdef _EDF_NODE_IDS_
183 for(TInt iConn = 0; iConn < aNbConn; iConn++)
184 aNodeIds[iConn] = aNodeInfo->GetElemNum(aConnSlice[iConn] - 1);
186 for(TInt iConn = 0; iConn < aNbConn; iConn++)
187 aNodeIds[iConn] = aConnSlice[iConn];
189 for(TInt iConn = 0; iConn < aNbConn; iConn++)
190 aNodeIds[iConn] = aConnSlice[iConn];
192 bool isRenum = false;
193 SMDS_MeshElement* anElement = NULL;
194 TInt aFamNum = aPolygoneInfo->GetFamNum(iElem);
198 TInt anElemId = aPolygoneInfo->GetElemNum(iElem);
199 anElement = myMesh->AddPolygonalFaceWithID(aNodeIds,anElemId);
202 std::vector<const SMDS_MeshNode*> aNodes(aNbConn);
203 for(TInt iConn = 0; iConn < aNbConn; iConn++)
204 aNodes[iConn] = FindNode(myMesh,aNodeIds[iConn]);
205 anElement = myMesh->AddPolygonalFace(aNodes);
206 isRenum = anIsElemNum;
208 }catch(const std::exception& exc){
215 aResult = DRS_WARN_SKIP_ELEM;
220 if(aResult < DRS_WARN_RENUMBER)
221 aResult = DRS_WARN_RENUMBER;
223 if(myFamilies.find(aFamNum) != myFamilies.end()){
224 // Save reference to this element from its family
225 myFamilies[aFamNum]->AddElement(anElement);
226 myFamilies[aFamNum]->SetType(anElement->GetType());
229 } // for (TInt iPG = 0; iPG < nbPolygons; iPG++)
233 PPolyedreInfo aPolyedreInfo = aMed->GetPPolyedreInfo(aMeshInfo,anEntity,aGeom);
234 EBooleen anIsElemNum = takeNumbers ? aPolyedreInfo->IsElemNum() : eFAUX;
236 TInt aNbElem = aPolyedreInfo->GetNbElem();
237 for(TInt iElem = 0; iElem < aNbElem; iElem++){
238 MED::TCConnSliceArr aConnSliceArr = aPolyedreInfo->GetConnSliceArr(iElem);
239 TInt aNbFaces = aConnSliceArr.size();
240 typedef std::vector<int> TQuantities;
241 TQuantities aQuantities(aNbFaces);
242 TInt aNbNodes = aPolyedreInfo->GetNbNodes(iElem);
243 TNodeIds aNodeIds(aNbNodes);
244 for(TInt iFace = 0, iNode = 0; iFace < aNbFaces; iFace++){
245 MED::TCConnSlice aConnSlice = aConnSliceArr[iFace];
246 TInt aNbConn = aConnSlice.size();
247 aQuantities[iFace] = aNbConn;
248 #ifdef _EDF_NODE_IDS_
250 for(TInt iConn = 0; iConn < aNbConn; iConn++)
251 aNodeIds[iNode++] = aNodeInfo->GetElemNum(aConnSlice[iConn] - 1);
253 for(TInt iConn = 0; iConn < aNbConn; iConn++)
254 aNodeIds[iNode++] = aConnSlice[iConn];
256 for(TInt iConn = 0; iConn < aNbConn; iConn++)
257 aNodeIds[iNode++] = aConnSlice[iConn];
261 bool isRenum = false;
262 SMDS_MeshElement* anElement = NULL;
263 TInt aFamNum = aPolyedreInfo->GetFamNum(iElem);
267 TInt anElemId = aPolyedreInfo->GetElemNum(iElem);
268 anElement = myMesh->AddPolyhedralVolumeWithID(aNodeIds,aQuantities,anElemId);
271 std::vector<const SMDS_MeshNode*> aNodes(aNbNodes);
272 for(TInt iConn = 0; iConn < aNbNodes; iConn++)
273 aNodes[iConn] = FindNode(myMesh,aNodeIds[iConn]);
274 anElement = myMesh->AddPolyhedralVolume(aNodes,aQuantities);
275 isRenum = anIsElemNum;
277 }catch(const std::exception& exc){
284 aResult = DRS_WARN_SKIP_ELEM;
289 if (aResult < DRS_WARN_RENUMBER)
290 aResult = DRS_WARN_RENUMBER;
292 if(myFamilies.find(aFamNum) != myFamilies.end()){
293 // Save reference to this element from its family
294 myFamilies[aFamNum]->AddElement(anElement);
295 myFamilies[aFamNum]->SetType(anElement->GetType());
298 } // for (int iPE = 0; iPE < nbPolyedres; iPE++)
302 PCellInfo aCellInfo = aMed->GetPCellInfo(aMeshInfo,anEntity,aGeom);
303 EBooleen anIsElemNum = takeNumbers ? aCellInfo->IsElemNum() : eFAUX;
304 TInt aNbElems = aCellInfo->GetNbElem();
305 if(MYDEBUG) MESSAGE("Perform - anEntity = "<<anEntity<<"; anIsElemNum = "<<anIsElemNum);
306 if(MYDEBUG) MESSAGE("Perform - aGeom = "<<aGeom<<"; aNbElems = "<<aNbElems);
308 for(int iElem = 0; iElem < aNbElems; iElem++){
341 TNodeIds aNodeIds(aNbNodes);
342 bool anIsValidConnect = false;
343 TCConnSlice aConnSlice = aCellInfo->GetConnSlice(iElem);
345 #ifdef _EDF_NODE_IDS_
347 for(int iNode = 0; iNode < aNbNodes; iNode++)
348 aNodeIds[iNode] = aNodeInfo->GetElemNum(aConnSlice[iNode] - 1);
350 for(int iNode = 0; iNode < aNbNodes; iNode++)
351 aNodeIds[iNode] = aConnSlice[iNode];
353 for(int iNode = 0; iNode < aNbNodes; iNode++)
354 aNodeIds[iNode] = aConnSlice[iNode];
356 anIsValidConnect = true;
357 }catch(const std::exception& exc){
358 //INFOS("Follow exception was cought:\n\t"<<exc.what());
361 //INFOS("Unknown exception was cought !!!");
365 if(!anIsValidConnect)
368 bool isRenum = false;
369 SMDS_MeshElement* anElement = NULL;
370 TInt aFamNum = aCellInfo->GetFamNum(iElem);
372 //MESSAGE("Try to create element # " << iElem << " with id = "
373 // << aCellInfo->GetElemNum(iElem));
378 anElement = myMesh->AddEdgeWithID(aNodeIds[0],
380 aCellInfo->GetElemNum(iElem));
382 anElement = myMesh->AddEdge(FindNode(myMesh,aNodeIds[0]),
383 FindNode(myMesh,aNodeIds[1]));
384 isRenum = anIsElemNum;
391 anElement = myMesh->AddFaceWithID(aNodeIds[0],
394 aCellInfo->GetElemNum(iElem));
396 anElement = myMesh->AddFace(FindNode(myMesh,aNodeIds[0]),
397 FindNode(myMesh,aNodeIds[1]),
398 FindNode(myMesh,aNodeIds[2]));
399 isRenum = anIsElemNum;
405 // There is some differnce between SMDS and MED
407 anElement = myMesh->AddFaceWithID(aNodeIds[0],
411 aCellInfo->GetElemNum(iElem));
413 anElement = myMesh->AddFace(FindNode(myMesh,aNodeIds[0]),
414 FindNode(myMesh,aNodeIds[1]),
415 FindNode(myMesh,aNodeIds[2]),
416 FindNode(myMesh,aNodeIds[3]));
417 isRenum = anIsElemNum;
424 anElement = myMesh->AddVolumeWithID(aNodeIds[0],
428 aCellInfo->GetElemNum(iElem));
430 anElement = myMesh->AddVolume(FindNode(myMesh,aNodeIds[0]),
431 FindNode(myMesh,aNodeIds[1]),
432 FindNode(myMesh,aNodeIds[2]),
433 FindNode(myMesh,aNodeIds[3]));
434 isRenum = anIsElemNum;
440 // There is some differnce between SMDS and MED
442 anElement = myMesh->AddVolumeWithID(aNodeIds[0],
447 aCellInfo->GetElemNum(iElem));
449 anElement = myMesh->AddVolume(FindNode(myMesh,aNodeIds[0]),
450 FindNode(myMesh,aNodeIds[1]),
451 FindNode(myMesh,aNodeIds[2]),
452 FindNode(myMesh,aNodeIds[3]),
453 FindNode(myMesh,aNodeIds[4]));
454 isRenum = anIsElemNum;
461 anElement = myMesh->AddVolumeWithID(aNodeIds[0],
467 aCellInfo->GetElemNum(iElem));
469 anElement = myMesh->AddVolume(FindNode(myMesh,aNodeIds[0]),
470 FindNode(myMesh,aNodeIds[1]),
471 FindNode(myMesh,aNodeIds[2]),
472 FindNode(myMesh,aNodeIds[3]),
473 FindNode(myMesh,aNodeIds[4]),
474 FindNode(myMesh,aNodeIds[5]));
475 isRenum = anIsElemNum;
482 anElement = myMesh->AddVolumeWithID(aNodeIds[0],
490 aCellInfo->GetElemNum(iElem));
492 anElement = myMesh->AddVolume(FindNode(myMesh,aNodeIds[0]),
493 FindNode(myMesh,aNodeIds[1]),
494 FindNode(myMesh,aNodeIds[2]),
495 FindNode(myMesh,aNodeIds[3]),
496 FindNode(myMesh,aNodeIds[4]),
497 FindNode(myMesh,aNodeIds[5]),
498 FindNode(myMesh,aNodeIds[6]),
499 FindNode(myMesh,aNodeIds[7]));
500 isRenum = anIsElemNum;
504 }catch(const std::exception& exc){
505 //INFOS("Follow exception was cought:\n\t"<<exc.what());
508 //INFOS("Unknown exception was cought !!!");
513 aResult = DRS_WARN_SKIP_ELEM;
519 if (aResult < DRS_WARN_RENUMBER)
520 aResult = DRS_WARN_RENUMBER;
522 if (myFamilies.find(aFamNum) != myFamilies.end()) {
523 // Save reference to this element from its family
524 myFamilies[aFamNum]->AddElement(anElement);
525 myFamilies[aFamNum]->SetType(anElement->GetType());
534 }catch(const std::exception& exc){
535 INFOS("Follow exception was cought:\n\t"<<exc.what());
538 INFOS("Unknown exception was cought !!!");
541 if(MYDEBUG) MESSAGE("Perform - aResult status = "<<aResult);
545 list<string> DriverMED_R_SMESHDS_Mesh::GetMeshNames(Status& theStatus)
547 list<string> aMeshNames;
550 if(MYDEBUG) MESSAGE("GetMeshNames - myFile : " << myFile);
552 PWrapper aMed = CrWrapper(myFile);
554 if (TInt aNbMeshes = aMed->GetNbMeshes()) {
555 for (int iMesh = 0; iMesh < aNbMeshes; iMesh++) {
556 // Reading the MED mesh
557 //---------------------
558 PMeshInfo aMeshInfo = aMed->GetPMeshInfo(iMesh+1);
559 aMeshNames.push_back(aMeshInfo->GetName());
562 }catch(const std::exception& exc){
563 INFOS("Follow exception was cought:\n\t"<<exc.what());
564 theStatus = DRS_FAIL;
566 INFOS("Unknown exception was cought !!!");
567 theStatus = DRS_FAIL;
573 list<string> DriverMED_R_SMESHDS_Mesh::GetGroupNames()
575 list<string> aResult;
576 set<string> aResGroupNames;
578 map<int, DriverMED_FamilyPtr>::iterator aFamsIter = myFamilies.begin();
579 for (; aFamsIter != myFamilies.end(); aFamsIter++)
581 DriverMED_FamilyPtr aFamily = (*aFamsIter).second;
582 const MED::TStringSet& aGroupNames = aFamily->GetGroupNames();
583 set<string>::iterator aGrNamesIter = aGroupNames.begin();
584 for (; aGrNamesIter != aGroupNames.end(); aGrNamesIter++)
586 string aName = *aGrNamesIter;
587 // Check, if this is a Group or SubMesh name
588 //if (aName.substr(0, 5) == string("Group")) {
589 if (aResGroupNames.find(aName) == aResGroupNames.end()) {
590 aResGroupNames.insert(aName);
591 aResult.push_back(aName);
600 void DriverMED_R_SMESHDS_Mesh::GetGroup(SMESHDS_Group* theGroup)
602 string aGroupName (theGroup->GetStoreName());
603 if(MYDEBUG) MESSAGE("Get Group " << aGroupName);
605 map<int, DriverMED_FamilyPtr>::iterator aFamsIter = myFamilies.begin();
606 for (; aFamsIter != myFamilies.end(); aFamsIter++)
608 DriverMED_FamilyPtr aFamily = (*aFamsIter).second;
609 if (aFamily->MemberOf(aGroupName))
611 const set<const SMDS_MeshElement *>& anElements = aFamily->GetElements();
612 set<const SMDS_MeshElement *>::iterator anElemsIter = anElements.begin();
613 const SMDS_MeshElement * element = 0;
614 for (; anElemsIter != anElements.end(); anElemsIter++)
616 element = *anElemsIter;
617 theGroup->SMDSGroup().Add(element);
620 theGroup->SetType( element->GetType() );
625 void DriverMED_R_SMESHDS_Mesh::GetSubMesh (SMESHDS_SubMesh* theSubMesh,
628 char submeshGrpName[ 30 ];
629 sprintf( submeshGrpName, "SubMesh %d", theId );
630 string aName (submeshGrpName);
631 map<int, DriverMED_FamilyPtr>::iterator aFamsIter = myFamilies.begin();
632 for (; aFamsIter != myFamilies.end(); aFamsIter++)
634 DriverMED_FamilyPtr aFamily = (*aFamsIter).second;
635 if (aFamily->MemberOf(aName))
637 const set<const SMDS_MeshElement *>& anElements = aFamily->GetElements();
638 set<const SMDS_MeshElement *>::iterator anElemsIter = anElements.begin();
639 if (aFamily->GetType() == SMDSAbs_Node)
641 for (; anElemsIter != anElements.end(); anElemsIter++)
643 const SMDS_MeshNode* node = static_cast<const SMDS_MeshNode*>(*anElemsIter);
644 theSubMesh->AddNode(node);
649 for (; anElemsIter != anElements.end(); anElemsIter++)
651 theSubMesh->AddElement(*anElemsIter);
658 void DriverMED_R_SMESHDS_Mesh::CreateAllSubMeshes ()
660 map<int, DriverMED_FamilyPtr>::iterator aFamsIter = myFamilies.begin();
661 for (; aFamsIter != myFamilies.end(); aFamsIter++)
663 DriverMED_FamilyPtr aFamily = (*aFamsIter).second;
664 MED::TStringSet aGroupNames = aFamily->GetGroupNames();
665 set<string>::iterator aGrNamesIter = aGroupNames.begin();
666 for (; aGrNamesIter != aGroupNames.end(); aGrNamesIter++)
668 string aName = *aGrNamesIter;
669 // Check, if this is a Group or SubMesh name
670 if (aName.substr(0, 7) == string("SubMesh"))
672 int Id = atoi(string(aName).substr(7).c_str());
673 set<const SMDS_MeshElement *> anElements = aFamily->GetElements();
674 set<const SMDS_MeshElement *>::iterator anElemsIter = anElements.begin();
675 if (aFamily->GetType() == SMDSAbs_Node)
677 for (; anElemsIter != anElements.end(); anElemsIter++)
679 SMDS_MeshNode* node = const_cast<SMDS_MeshNode*>
680 ( static_cast<const SMDS_MeshNode*>( *anElemsIter ));
681 // find out a shape type
682 TopoDS_Shape aShape = myMesh->IndexToShape( Id );
683 int aShapeType = ( aShape.IsNull() ? -1 : aShape.ShapeType() );
684 switch ( aShapeType ) {
686 myMesh->SetNodeOnFace(node, Id); break;
688 myMesh->SetNodeOnEdge(node, Id); break;
690 myMesh->SetNodeOnVertex(node, Id); break;
692 myMesh->SetNodeInVolume(node, Id);
698 for (; anElemsIter != anElements.end(); anElemsIter++)
700 myMesh->SetMeshElementOnShape(*anElemsIter, Id);