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 "utilities.h"
31 #include "DriverMED_Family.h"
33 #include "SMESHDS_Group.hxx"
35 #include "MEDA_Wrapper.hxx"
36 #include "MED_Utilities.hxx"
40 #define _EDF_NODE_IDS_
42 DriverMED_R_SMESHDS_Mesh::DriverMED_R_SMESHDS_Mesh()
51 DriverMED_R_SMESHDS_Mesh::~DriverMED_R_SMESHDS_Mesh()
53 // map<int, DriverMED_FamilyPtr>::iterator aFamsIter = myFamilies.begin();
54 // for (; aFamsIter != myFamilies.end(); aFamsIter++)
56 // delete (*aFamsIter).second;
60 void DriverMED_R_SMESHDS_Mesh::SetMesh(SMDS_Mesh * aMesh)
65 void DriverMED_R_SMESHDS_Mesh::SetFile(string aFile)
70 void DriverMED_R_SMESHDS_Mesh::SetFileId(med_idt aFileId)
75 void DriverMED_R_SMESHDS_Mesh::SetMeshId(int aMeshId)
80 void DriverMED_R_SMESHDS_Mesh::SetMeshName(string theMeshName)
82 myMeshName = theMeshName;
85 void DriverMED_R_SMESHDS_Mesh::Read()
88 string myClass = string("SMDS_Mesh");
89 string myExtension = string("MED");
91 DriverMED_R_SMDS_Mesh *myReader = new DriverMED_R_SMDS_Mesh;
93 myReader->SetMesh(myMesh);
94 myReader->SetMeshId(myMeshId);
95 myReader->SetFile(myFile);
96 myReader->SetFileId(-1);
101 void DriverMED_R_SMESHDS_Mesh::Add()
103 string myClass = string("SMDS_Mesh");
104 string myExtension = string("MED");
106 DriverMED_R_SMDS_Mesh *myReader = new DriverMED_R_SMDS_Mesh;
108 myReader->SetMesh(myMesh);
109 myReader->SetMeshId(myMeshId);
112 myReader->SetFileId(myFileId);
118 static const SMDS_MeshNode*
119 FindNode(const SMDS_Mesh* theMesh, med_int theId){
120 const SMDS_MeshNode* aNode = theMesh->FindNode(theId);
121 if(aNode) return aNode;
122 EXCEPTION(runtime_error,"SMDS_Mesh::FindNode - cannot find a SMDS_MeshNode for ID = "<<theId);
126 enum ECoordName{eX, eY, eZ, eNone};
127 typedef med_float (*TGetCoord)(MEDA::PNodeInfo&, med_int);
129 template<ECoordName TheCoordId>
130 med_float GetCoord(MEDA::PNodeInfo& thePNodeInfo, med_int theElemId){
131 return thePNodeInfo->GetNodeCoord(theElemId,TheCoordId);
135 med_float GetCoord<eNone>(MEDA::PNodeInfo& thePNodeInfo, med_int theElemId){
140 static TGetCoord aXYZGetCoord[3] = {
147 static TGetCoord aXYGetCoord[3] = {
153 static TGetCoord aYZGetCoord[3] = {
159 static TGetCoord aXZGetCoord[3] = {
166 static TGetCoord aXGetCoord[3] = {
172 static TGetCoord aYGetCoord[3] = {
178 static TGetCoord aZGetCoord[3] = {
186 MEDA::PNodeInfo myPNodeInfo;
187 TGetCoord* myGetCoord;
189 TCoordHelper(const MEDA::PNodeInfo& thePNodeInfo,
190 TGetCoord* theGetCoord):
191 myPNodeInfo(thePNodeInfo),
192 myGetCoord(theGetCoord)
194 virtual ~TCoordHelper(){}
195 med_float GetCoord(med_int theElemId, med_int theCoodId){
196 return (*myGetCoord[theCoodId])(myPNodeInfo,theElemId);
199 typedef boost::shared_ptr<TCoordHelper> TCoordHelperPtr;
202 DriverMED_R_SMESHDS_Mesh::ReadStatus DriverMED_R_SMESHDS_Mesh::ReadMySelf()
204 ReadStatus result = DRS_FAIL;
206 using namespace MEDA;
209 MESSAGE("ReadMySelf - myFile : "<<myFile);
210 TWrapper aMed(myFile);
213 if(med_int aNbMeshes = aMed.GetNbMeshes()){
214 for(int iMesh = 0; iMesh < aNbMeshes; iMesh++){
215 // Reading the MED mesh
216 //---------------------
217 PMeshInfo aMeshInfo = aMed.GetMeshInfo(iMesh);
219 if (myMeshId != -1) {
220 ostringstream aMeshNameStr;
221 aMeshNameStr<<myMeshId;
222 aMeshName = aMeshNameStr.str();
224 aMeshName = myMeshName;
226 MESSAGE("ReadMySelf - aMeshName : "<<aMeshName<<"; "<<aMeshInfo->GetName());
227 if(aMeshName != aMeshInfo->GetName()) continue;
230 // Reading MED families to the temporary structure
231 //------------------------------------------------
232 med_int aNbFams = aMed.GetNbFamilies(aMeshInfo);
233 MESSAGE("Read " << aNbFams << " families");
234 for (med_int iFam = 0; iFam < aNbFams; iFam++) {
235 PFamilyInfo aFamilyInfo = aMed.GetFamilyInfo(aMeshInfo, iFam);
236 med_int aFamId = aFamilyInfo->GetId();
237 MESSAGE("Family " << aFamId << " :");
239 DriverMED_FamilyPtr aFamily (new DriverMED_Family);
241 med_int aNbGrp = aFamilyInfo->GetNbGroup();
242 MESSAGE("belong to " << aNbGrp << " groups");
243 for (med_int iGr = 0; iGr < aNbGrp; iGr++) {
244 string aGroupName = aFamilyInfo->GetGroupName(iGr);
246 aFamily->AddGroupName(aGroupName);
248 myFamilies[aFamId] = aFamily;
251 // Reading MED nodes to the corresponding SMDS structure
252 //------------------------------------------------------
253 PNodeInfo aNodeInfo = aMed.GetNodeInfo(aMeshInfo);
255 TCoordHelperPtr aCoordHelperPtr;
257 med_int aMeshDimension = aMeshInfo->GetDim();
258 bool anIsDimPresent[3] = {false, false, false};
259 for(med_int iDim = 0; iDim < aMeshDimension; iDim++){
260 string aDimName = aNodeInfo->GetCoordName(iDim);
261 if(aDimName == "x" || aDimName == "X")
262 anIsDimPresent[eX] = true;
263 else if(aDimName == "y" || aDimName == "Y")
264 anIsDimPresent[eY] = true;
265 else if(aDimName == "z" || aDimName == "Z")
266 anIsDimPresent[eZ] = true;
268 switch(aMeshDimension){
270 aCoordHelperPtr.reset(new TCoordHelper(aNodeInfo,aXYZGetCoord));
273 if(anIsDimPresent[eY] && anIsDimPresent[eZ])
274 aCoordHelperPtr.reset(new TCoordHelper(aNodeInfo,aYZGetCoord));
275 else if(anIsDimPresent[eX] && anIsDimPresent[eZ])
276 aCoordHelperPtr.reset(new TCoordHelper(aNodeInfo,aXZGetCoord));
278 aCoordHelperPtr.reset(new TCoordHelper(aNodeInfo,aXYGetCoord));
281 if(anIsDimPresent[eY])
282 aCoordHelperPtr.reset(new TCoordHelper(aNodeInfo,aYGetCoord));
283 else if(anIsDimPresent[eZ])
284 aCoordHelperPtr.reset(new TCoordHelper(aNodeInfo,aZGetCoord));
286 aCoordHelperPtr.reset(new TCoordHelper(aNodeInfo,aXGetCoord));
291 med_booleen anIsNodeNum = aNodeInfo->IsElemNum();
292 med_int aNbElems = aNodeInfo->GetNbElem();
293 MESSAGE("ReadMySelf - aNodeInfo->GetNbElem() = "<<aNbElems<<"; anIsNodeNum = "<<anIsNodeNum);
294 for(med_int iElem = 0; iElem < aNbElems; iElem++){
295 double aCoords[3] = {0.0, 0.0, 0.0};
296 for(med_int iDim = 0; iDim < 3; iDim++)
297 aCoords[iDim] = aCoordHelperPtr->GetCoord(iElem,iDim);
298 const SMDS_MeshNode* aNode;
300 aNode = myMesh->AddNodeWithID
301 (aCoords[0],aCoords[1],aCoords[2],aNodeInfo->GetElemNum(iElem));
303 aNode = myMesh->AddNode
304 (aCoords[0],aCoords[1],aCoords[2]);
306 //cout<<aNode->GetID()<<": "<<aNode->X()<<", "<<aNode->Y()<<", "<<aNode->Z()<<endl;
308 // Save reference to this node from its family
309 med_int aFamNum = aNodeInfo->GetFamNum(iElem);
310 if (myFamilies.find(aFamNum) != myFamilies.end())
312 myFamilies[aFamNum]->AddElement(aNode);
313 myFamilies[aFamNum]->SetType(SMDSAbs_Node);
317 // Reading pre information about all MED cells
318 //--------------------------------------------
319 bool takeNumbers = true; // initially we trust the numbers from file
320 MED::TEntityInfo aEntityInfo = aMed.GetEntityInfo(aMeshInfo);
321 MED::TEntityInfo::iterator anEntityIter = aEntityInfo.begin();
322 for(; anEntityIter != aEntityInfo.end(); anEntityIter++){
323 const med_entite_maillage& anEntity = anEntityIter->first;
324 if(anEntity == MED_NOEUD) continue;
325 // Reading MED cells to the corresponding SMDS structure
326 //------------------------------------------------------
327 const MED::TGeom& aTGeom = anEntityIter->second;
328 MED::TGeom::const_iterator anTGeomIter = aTGeom.begin();
329 for(; anTGeomIter != aTGeom.end(); anTGeomIter++){
330 const med_geometrie_element& aGeom = anTGeomIter->first;
331 if(aGeom == MED_POINT1) continue;
332 PCellInfo aCellInfo = aMed.GetCellInfo(aMeshInfo,anEntity,aGeom);
333 med_booleen anIsElemNum = takeNumbers ? aCellInfo->IsElemNum() : MED_FAUX;
334 med_int aNbElems = aCellInfo->GetNbElem();
335 MESSAGE("ReadMySelf - anEntity = "<<anEntity<<"; anIsElemNum = "<<anIsElemNum);
336 MESSAGE("ReadMySelf - aGeom = "<<aGeom<<"; aNbElems = "<<aNbElems);
338 for(int iElem = 0; iElem < aNbElems; iElem++){
339 med_int aNbNodes = -1;
371 vector<med_int> aNodeIds(aNbNodes);
372 #ifdef _EDF_NODE_IDS_
374 for(int i = 0; i < aNbNodes; i++){
375 aNodeIds[i] = aNodeInfo->GetElemNum(aCellInfo->GetConn(iElem,i)-1);
378 for(int i = 0; i < aNbNodes; i++){
379 aNodeIds[i] = aCellInfo->GetConn(iElem,i);
383 for(int i = 0; i < aNbNodes; i++){
384 aNodeIds[i] = aCellInfo->GetConn(iElem,i);
388 bool isRenum = false;
389 SMDS_MeshElement* anElement = NULL;
390 med_int aFamNum = aCellInfo->GetFamNum(iElem);
396 anElement = myMesh->AddEdgeWithID(aNodeIds[0],
398 aCellInfo->GetElemNum(iElem));
400 anElement = myMesh->AddEdge(FindNode(myMesh,aNodeIds[0]),
401 FindNode(myMesh,aNodeIds[1]));
402 isRenum = anIsElemNum;
409 anElement = myMesh->AddFaceWithID(aNodeIds[0],
412 aCellInfo->GetElemNum(iElem));
414 anElement = myMesh->AddFace(FindNode(myMesh,aNodeIds[0]),
415 FindNode(myMesh,aNodeIds[1]),
416 FindNode(myMesh,aNodeIds[2]));
417 isRenum = anIsElemNum;
423 // There is some differnce between SMDS and MED
425 anElement = myMesh->AddFaceWithID(aNodeIds[0],
429 aCellInfo->GetElemNum(iElem));
431 anElement = myMesh->AddFace(FindNode(myMesh,aNodeIds[0]),
432 FindNode(myMesh,aNodeIds[1]),
433 FindNode(myMesh,aNodeIds[2]),
434 FindNode(myMesh,aNodeIds[3]));
435 isRenum = anIsElemNum;
442 anElement = myMesh->AddVolumeWithID(aNodeIds[0],
446 aCellInfo->GetElemNum(iElem));
448 anElement = myMesh->AddVolume(FindNode(myMesh,aNodeIds[0]),
449 FindNode(myMesh,aNodeIds[1]),
450 FindNode(myMesh,aNodeIds[2]),
451 FindNode(myMesh,aNodeIds[3]));
452 isRenum = anIsElemNum;
458 // There is some differnce between SMDS and MED
460 anElement = myMesh->AddVolumeWithID(aNodeIds[0],
465 aCellInfo->GetElemNum(iElem));
467 anElement = myMesh->AddVolume(FindNode(myMesh,aNodeIds[0]),
468 FindNode(myMesh,aNodeIds[1]),
469 FindNode(myMesh,aNodeIds[2]),
470 FindNode(myMesh,aNodeIds[3]),
471 FindNode(myMesh,aNodeIds[4]));
472 isRenum = anIsElemNum;
479 anElement = myMesh->AddVolumeWithID(aNodeIds[0],
485 aCellInfo->GetElemNum(iElem));
487 anElement = myMesh->AddVolume(FindNode(myMesh,aNodeIds[0]),
488 FindNode(myMesh,aNodeIds[1]),
489 FindNode(myMesh,aNodeIds[2]),
490 FindNode(myMesh,aNodeIds[3]),
491 FindNode(myMesh,aNodeIds[4]),
492 FindNode(myMesh,aNodeIds[5]));
493 isRenum = anIsElemNum;
500 anElement = myMesh->AddVolumeWithID(aNodeIds[0],
508 aCellInfo->GetElemNum(iElem));
510 anElement = myMesh->AddVolume(FindNode(myMesh,aNodeIds[0]),
511 FindNode(myMesh,aNodeIds[1]),
512 FindNode(myMesh,aNodeIds[2]),
513 FindNode(myMesh,aNodeIds[3]),
514 FindNode(myMesh,aNodeIds[4]),
515 FindNode(myMesh,aNodeIds[5]),
516 FindNode(myMesh,aNodeIds[6]),
517 FindNode(myMesh,aNodeIds[7]));
518 isRenum = anIsElemNum;
522 }catch(const std::exception& exc){
523 //INFOS("Follow exception was cought:\n\t"<<exc.what());
526 //INFOS("Unknown exception was cought !!!");
531 result = DRS_WARN_SKIP_ELEM;
535 anIsElemNum = MED_FAUX;
537 if (result < DRS_WARN_RENUMBER)
538 result = DRS_WARN_RENUMBER;
540 if (myFamilies.find(aFamNum) != myFamilies.end()) {
541 // Save reference to this element from its family
542 myFamilies[aFamNum]->AddElement(anElement);
543 myFamilies[aFamNum]->SetType(anElement->GetType());
552 }catch(const std::exception& exc){
553 INFOS("Follow exception was cought:\n\t"<<exc.what());
556 INFOS("Unknown exception was cought !!!");
559 MESSAGE("ReadMySelf - result status = "<<result);
563 list<string> DriverMED_R_SMESHDS_Mesh::GetMeshNames()
565 list<string> aMeshNames;
568 using namespace MEDA;
570 MESSAGE("GetMeshNames - myFile : " << myFile);
571 TWrapper aMed (myFile);
573 if (med_int aNbMeshes = aMed.GetNbMeshes()) {
574 for (int iMesh = 0; iMesh < aNbMeshes; iMesh++) {
575 // Reading the MED mesh
576 //---------------------
577 PMeshInfo aMeshInfo = aMed.GetMeshInfo(iMesh);
578 aMeshNames.push_back(aMeshInfo->GetName());
581 }catch(const std::exception& exc){
582 INFOS("Follow exception was cought:\n\t"<<exc.what());
584 INFOS("Unknown exception was cought !!!");
590 list<string> DriverMED_R_SMESHDS_Mesh::GetGroupNames()
592 list<string> aResult;
593 set<string> aResGroupNames;
595 map<int, DriverMED_FamilyPtr>::iterator aFamsIter = myFamilies.begin();
596 for (; aFamsIter != myFamilies.end(); aFamsIter++)
598 DriverMED_FamilyPtr aFamily = (*aFamsIter).second;
599 const MED::TStringSet& aGroupNames = aFamily->GetGroupNames();
600 set<string>::iterator aGrNamesIter = aGroupNames.begin();
601 for (; aGrNamesIter != aGroupNames.end(); aGrNamesIter++)
603 string aName = *aGrNamesIter;
604 // Check, if this is a Group or SubMesh name
605 //if (aName.substr(0, 5) == string("Group")) {
606 if (aResGroupNames.find(aName) == aResGroupNames.end()) {
607 aResGroupNames.insert(aName);
608 aResult.push_back(aName);
617 void DriverMED_R_SMESHDS_Mesh::GetGroup(SMESHDS_Group* theGroup)
619 string aGroupName (theGroup->GetStoreName());
620 MESSAGE("Get Group " << aGroupName);
622 map<int, DriverMED_FamilyPtr>::iterator aFamsIter = myFamilies.begin();
623 for (; aFamsIter != myFamilies.end(); aFamsIter++)
625 DriverMED_FamilyPtr aFamily = (*aFamsIter).second;
626 if (aFamily->MemberOf(aGroupName))
628 const set<const SMDS_MeshElement *>& anElements = aFamily->GetElements();
629 set<const SMDS_MeshElement *>::iterator anElemsIter = anElements.begin();
630 for (; anElemsIter != anElements.end(); anElemsIter++)
632 theGroup->SMDS_MeshGroup::Add(*anElemsIter);
638 void DriverMED_R_SMESHDS_Mesh::GetSubMesh (SMESHDS_SubMesh* theSubMesh,
641 char submeshGrpName[ 30 ];
642 sprintf( submeshGrpName, "SubMesh %d", theId );
643 string aName (submeshGrpName);
644 map<int, DriverMED_FamilyPtr>::iterator aFamsIter = myFamilies.begin();
645 for (; aFamsIter != myFamilies.end(); aFamsIter++)
647 DriverMED_FamilyPtr aFamily = (*aFamsIter).second;
648 if (aFamily->MemberOf(aName))
650 const set<const SMDS_MeshElement *>& anElements = aFamily->GetElements();
651 set<const SMDS_MeshElement *>::iterator anElemsIter = anElements.begin();
652 if (aFamily->GetType() == SMDSAbs_Node)
654 for (; anElemsIter != anElements.end(); anElemsIter++)
656 const SMDS_MeshNode* node = static_cast<const SMDS_MeshNode*>(*anElemsIter);
657 theSubMesh->AddNode(node);
662 for (; anElemsIter != anElements.end(); anElemsIter++)
664 theSubMesh->AddElement(*anElemsIter);
671 void DriverMED_R_SMESHDS_Mesh::CreateAllSubMeshes ()
673 SMESHDS_Mesh* aSMESHDSMesh = dynamic_cast<SMESHDS_Mesh*>(myMesh);
675 EXCEPTION(runtime_error,"Can not cast SMDS_Mesh to SMESHDS_Mesh");
677 map<int, DriverMED_FamilyPtr>::iterator aFamsIter = myFamilies.begin();
678 for (; aFamsIter != myFamilies.end(); aFamsIter++)
680 DriverMED_FamilyPtr aFamily = (*aFamsIter).second;
681 MED::TStringSet aGroupNames = aFamily->GetGroupNames();
682 set<string>::iterator aGrNamesIter = aGroupNames.begin();
683 for (; aGrNamesIter != aGroupNames.end(); aGrNamesIter++)
685 string aName = *aGrNamesIter;
686 // Check, if this is a Group or SubMesh name
687 if (aName.substr(0, 7) == string("SubMesh"))
689 int Id = atoi(string(aName).substr(7).c_str());
690 set<const SMDS_MeshElement *> anElements = aFamily->GetElements();
691 set<const SMDS_MeshElement *>::iterator anElemsIter = anElements.begin();
692 if (aFamily->GetType() == SMDSAbs_Node)
694 for (; anElemsIter != anElements.end(); anElemsIter++)
696 const SMDS_MeshNode* node = static_cast<const SMDS_MeshNode*>(*anElemsIter);
697 aSMESHDSMesh->SetNodeInVolume(node, Id);
698 // aSMESHDSMesh->SetNodeOnFace(node, Id);
699 // aSMESHDSMesh->SetNodeOnEdge(node, Id);
700 // aSMESHDSMesh->SetNodeOnVertex(node, Id);
705 for (; anElemsIter != anElements.end(); anElemsIter++)
707 aSMESHDSMesh->SetMeshElementOnShape(*anElemsIter, Id);