1 // Copyright (C) 2007-2008 CEA/DEN, EDF R&D
3 // This library is free software; you can redistribute it and/or
4 // modify it under the terms of the GNU Lesser General Public
5 // License as published by the Free Software Foundation; either
6 // version 2.1 of the License.
8 // This library is distributed in the hope that it will be useful,
9 // but WITHOUT ANY WARRANTY; without even the implied warranty of
10 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
11 // Lesser General Public License for more details.
13 // You should have received a copy of the GNU Lesser General Public
14 // License along with this library; if not, write to the Free Software
15 // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
17 // See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com
19 #include "MEDLoader.hxx"
20 #include "CellModel.hxx"
21 #include "ParaMESH.hxx"
22 #include "BlockTopology.hxx"
23 #include "MEDCouplingUMesh.hxx"
35 med_geometrie_element typmai[MED_NBR_GEOMETRIE_MAILLE] = { MED_POINT1,
51 INTERP_KERNEL::NormalizedCellType typmai2[MED_NBR_GEOMETRIE_MAILLE] = { INTERP_KERNEL::NORM_ERROR,
52 INTERP_KERNEL::NORM_SEG2,
53 INTERP_KERNEL::NORM_SEG3,
54 INTERP_KERNEL::NORM_TRI3,
55 INTERP_KERNEL::NORM_QUAD4,
56 INTERP_KERNEL::NORM_QUAD8,
57 INTERP_KERNEL::NORM_TETRA4,
58 INTERP_KERNEL::NORM_TETRA10,
59 INTERP_KERNEL::NORM_HEXA8,
60 INTERP_KERNEL::NORM_HEXA20,
61 INTERP_KERNEL::NORM_PENTA6,
62 INTERP_KERNEL::NORM_PENTA15,
63 INTERP_KERNEL::NORM_PYRA5,
64 INTERP_KERNEL::NORM_PYRA13 };
66 using namespace ParaMEDMEM;
68 const char WHITE_SPACES[]=" \n";
70 MEDLoader::MEDConnOfOneElemType::MEDConnOfOneElemType(INTERP_KERNEL::NormalizedCellType type, int *conn, int lgth):_lgth(lgth),
71 _conn(conn),_global(0),
76 void MEDLoader::MEDConnOfOneElemType::setGlobal(int *global)
86 void MEDLoader::MEDConnOfOneElemType::releaseArray()
92 std::string buildStringFromFortran(const char *expr, int lgth)
94 std::string ret(expr,lgth);
95 std::string whiteSpaces(WHITE_SPACES);
96 std::size_t lgthReal=strlen(ret.c_str());
97 std::string ret2=ret.substr(0,lgthReal);
98 std::size_t found=ret2.find_last_not_of(whiteSpaces);
99 if (found!=std::string::npos)
102 ret2.clear();//ret is all whitespace
108 med_int getIdFromMeshName(med_idt fid, const char *meshName) throw(INTERP_KERNEL::Exception)
112 med_int n=MEDnMaa(fid);
114 throw INTERP_KERNEL::Exception("No mesh in file.");
115 med_maillage type_maillage;
116 char maillage_description[MED_TAILLE_DESC+1];
118 char nommaa[MED_TAILLE_NOM+1];
119 std::ostringstream os;
120 for(med_int i=1;i<=n;i++)
122 MEDmaaInfo(fid,i,nommaa,&dim,&type_maillage,maillage_description);
123 std::string cur=buildStringFromFortran(nommaa,sizeof(nommaa));
126 os << "\'" << cur.c_str() << "\' ";
128 std::ostringstream os2;
129 os2 << "MeshName '" << meshName << "' not in file : meshes available : " << os.str();
130 throw INTERP_KERNEL::Exception(os2.str().c_str());
133 void readUMeshDataInMedFile(med_idt fid, med_int meshId, double *&coords, int& nCoords, int& spaceDim, std::list<MEDLoader::MEDConnOfOneElemType>& conn)
135 char nommaa[MED_TAILLE_NOM+1];
136 char maillage_description[MED_TAILLE_DESC+1];
137 char comp[3*MED_TAILLE_PNOM+1];
138 char unit[3*MED_TAILLE_PNOM+1];
139 med_maillage type_maillage;
141 MEDmaaInfo(fid,meshId,nommaa,&Mdim,&type_maillage,maillage_description);
143 nCoords=MEDnEntMaa(fid,nommaa,MED_COOR,MED_NOEUD,(med_geometrie_element)0,(med_connectivite)0);
144 coords=new double[nCoords*spaceDim];
146 MEDcoordLire(fid,nommaa,Mdim,coords,MED_FULL_INTERLACE,MED_ALL,NULL,0,&repere,comp,unit);
147 med_booleen inoele, inuele;
148 for(int i=0;i<MED_NBR_GEOMETRIE_MAILLE;i++)
150 med_geometrie_element curMedType=typmai[i];
151 med_entite_maillage whichEntity;
152 int curNbOfElemM=MEDnEntMaa(fid,nommaa,MED_CONN,MED_MAILLE,curMedType,MED_NOD);
153 int curNbOfElemF=MEDnEntMaa(fid,nommaa,MED_CONN,MED_FACE,curMedType,MED_NOD);
155 if(curNbOfElemF>curNbOfElemM)
157 curNbOfElem=curNbOfElemF;
158 whichEntity=MED_FACE;
162 curNbOfElem=curNbOfElemM;
163 whichEntity=MED_MAILLE;
167 int *connTab=new int[(curMedType%100)*curNbOfElem];
168 MEDLoader::MEDConnOfOneElemType elem(typmai2[i],connTab,curNbOfElem);
169 int *tmp=new int[curNbOfElem];
170 int *fam=new int[curNbOfElem];
171 char *noms=new char[MED_TAILLE_PNOM*curNbOfElem+1];
172 MEDelementsLire(fid,nommaa,Mdim,connTab,MED_FULL_INTERLACE,noms,&inoele,tmp,&inuele,fam,curNbOfElem,whichEntity,curMedType,MED_NOD);
176 //trying to read global numbering
177 int *globArr=new int[curNbOfElem];
178 if(MEDglobalNumLire(fid,nommaa,globArr,curNbOfElem,whichEntity,curMedType)==0)
179 elem.setGlobal(globArr);
182 conn.push_back(elem);
188 unsigned MEDLoader::calculateHighestMeshDim(const std::list<MEDLoader::MEDConnOfOneElemType>& conn)
191 for(std::list<MEDLoader::MEDConnOfOneElemType>::const_iterator iter=conn.begin();iter!=conn.end();iter++)
193 unsigned curDim=INTERP_KERNEL::CellModel::getCellModel((*iter).getType()).getDimension();
200 void MEDLoader::keepSpecifiedMeshDim(std::list<MEDLoader::MEDConnOfOneElemType>& conn, unsigned meshDim)
202 for(std::list<MEDLoader::MEDConnOfOneElemType>::iterator iter=conn.begin();iter!=conn.end();)
204 unsigned curDim=INTERP_KERNEL::CellModel::getCellModel((*iter).getType()).getDimension();
207 (*iter).releaseArray();
208 iter=conn.erase(iter);
215 void MEDLoader::tradMEDFileCoreFrmt2MEDCouplingUMesh(const std::list<MEDLoader::MEDConnOfOneElemType>& medConnFrmt,
217 DataArrayInt* &connIndex)
219 if(medConnFrmt.empty())
225 std::list<MEDLoader::MEDConnOfOneElemType>::const_iterator iter=medConnFrmt.begin();
226 int totalNbOfCells=0;
227 int totalNbOfMedConn=0;
228 for(;iter!=medConnFrmt.end();iter++)
230 const INTERP_KERNEL::CellModel& cellMod=INTERP_KERNEL::CellModel::getCellModel((*iter).getType());
231 totalNbOfCells+=(*iter).getLength();
232 if(!cellMod.isDynamic())
233 totalNbOfMedConn+=(*iter).getLength()*cellMod.getNumberOfNodes();
235 throw INTERP_KERNEL::Exception("Polyg/polh not implemented yet !");
237 connIndex=DataArrayInt::New();
238 conn=DataArrayInt::New();
239 connIndex->alloc(totalNbOfCells+1,1);
240 int *connIdxPtr=connIndex->getPointer();
242 conn->alloc(totalNbOfMedConn+totalNbOfCells,1);
243 int *connPtr=conn->getPointer();
244 for(iter=medConnFrmt.begin();iter!=medConnFrmt.end();iter++)
246 INTERP_KERNEL::NormalizedCellType type=(*iter).getType();
247 int *sourceConn=(*iter).getArray();
248 const INTERP_KERNEL::CellModel& cellMod=INTERP_KERNEL::CellModel::getCellModel(type);
249 int nbOfCellsInCurType;
250 int nbOfNodesIn1Cell=cellMod.getNumberOfNodes();
251 if(!cellMod.isDynamic())
252 nbOfCellsInCurType=(*iter).getLength();
254 throw INTERP_KERNEL::Exception("Polyg/polh not implemented yet !");
255 if(!cellMod.isDynamic())
257 for(int i=0;i<nbOfCellsInCurType;i++,connIdxPtr++)
259 *connIdxPtr=connFillId;
261 connPtr=std::transform(sourceConn,sourceConn+nbOfNodesIn1Cell,connPtr,std::bind2nd(std::minus<int>(),1));
262 connFillId+=nbOfNodesIn1Cell+1;
263 sourceConn+=nbOfNodesIn1Cell;
265 *connIdxPtr=connFillId;
270 void MEDLoader::releaseMEDFileCoreFrmt(std::list<MEDLoader::MEDConnOfOneElemType>& medConnFrmt)
272 for(std::list<MEDLoader::MEDConnOfOneElemType>::iterator iter=medConnFrmt.begin();iter!=medConnFrmt.end();iter++)
273 (*iter).releaseArray();
278 * This method builds a sub set of connectivity for a given type 'type'.
279 * @param conn input containing connectivity with MEDCoupling format.
280 * @param connIndex input containing connectivity index in MEDCoupling format.
281 * @param type input specifying which cell types will be extracted in conn4MEDFile.
282 * @param conn4MEDFile output containing the connectivity directly understandable by MEDFile; conn4MEDFile has to be empty before this method called.
283 * @return nb of elements extracted.
285 int MEDLoader::buildMEDSubConnectivityOfOneType(DataArrayInt *conn, DataArrayInt *connIndex, INTERP_KERNEL::NormalizedCellType type, std::vector<int>& conn4MEDFile)
288 int nbOfElem=connIndex->getNbOfElems()-1;
289 const int *connPtr=conn->getPointer();
290 const int *connIdxPtr=connIndex->getPointer();
291 for(int i=0;i<nbOfElem;i++)
293 int delta=connIdxPtr[1]-connIdxPtr[0];
296 conn4MEDFile.insert(conn4MEDFile.end(),connPtr+1,connPtr+delta);
302 std::transform(conn4MEDFile.begin(),conn4MEDFile.end(),conn4MEDFile.begin(),std::bind2nd(std::plus<int>(),1));
306 MEDCouplingUMesh *MEDLoader::ReadUMeshFromFile(const char *fileName, const char *meshName, int meshDimRelToMax) throw(INTERP_KERNEL::Exception)
308 //Extraction data from MED file.
309 med_idt fid=MEDouvrir((char *)fileName,MED_LECTURE);
310 med_int mid=getIdFromMeshName(fid,meshName);
311 unsigned meshDimExtract;
315 std::list<MEDLoader::MEDConnOfOneElemType> conn;
316 readUMeshDataInMedFile(fid,mid,coords,nCoords,spaceDim,conn);
317 meshDimExtract=calculateHighestMeshDim(conn);
318 meshDimExtract=meshDimExtract+meshDimRelToMax;
319 keepSpecifiedMeshDim(conn,meshDimExtract);
321 //Put data in returned data structure.
322 MEDCouplingUMesh *ret=MEDCouplingUMesh::New();
323 ret->setName(meshName);
324 ret->setMeshDimension(meshDimExtract);
326 DataArrayDouble *coordsArr=DataArrayDouble::New();
327 coordsArr->useArray(coords,true,ParaMEDMEM::CPP_DEALLOC,nCoords,spaceDim);
328 ret->setCoords(coordsArr);
329 coordsArr->decrRef();
331 DataArrayInt *connArr,*connIndexArr;
332 tradMEDFileCoreFrmt2MEDCouplingUMesh(conn,connArr,connIndexArr);
333 ret->setConnectivity(connArr,connIndexArr);
338 connIndexArr->decrRef();
339 releaseMEDFileCoreFrmt(conn);
343 void MEDLoader::writeUMesh(const char *fileName, ParaMEDMEM::MEDCouplingUMesh *mesh)
345 med_idt fid=MEDouvrir((char *)fileName,MED_CREATION);
346 char maa[MED_TAILLE_NOM+1];
347 std::fill(maa,maa+MED_TAILLE_NOM+1,'\0');
348 const char *meshName=mesh->getName();
349 strcpy(maa,meshName);
350 MEDmaaCr(fid,maa,mesh->getMeshDimension(),MED_NON_STRUCTURE,maa);
351 std::set<INTERP_KERNEL::NormalizedCellType> allTypes(mesh->getAllTypes());
352 DataArrayInt *conn=mesh->getNodalConnectivity();
353 DataArrayInt *connIndex=mesh->getNodalConnectivityIndex();
354 char familyName[MED_TAILLE_NOM+1];
355 std::fill(familyName,familyName+MED_TAILLE_NOM+1,'\0');
356 const char DftFamilyName[]="DftFamily";
357 std::copy(DftFamilyName,DftFamilyName+sizeof(DftFamilyName),familyName);
358 for(int i=0;i<MED_NBR_GEOMETRIE_MAILLE;i++)
360 med_geometrie_element curMedType=typmai[i];
361 INTERP_KERNEL::NormalizedCellType curType=typmai2[i];
362 if(allTypes.find(curType)!=allTypes.end())
364 std::vector<int> medConn;
365 int nbOfElt=buildMEDSubConnectivityOfOneType(conn,connIndex,curType,medConn);
366 MEDconnEcr(fid,maa,mesh->getMeshDimension(),&medConn[0],MED_FULL_INTERLACE,nbOfElt,MED_MAILLE,curMedType,MED_NOD);
369 MEDfamCr(fid,maa,familyName,0,0,0,0,0,0,0);
370 DataArrayDouble *arr=mesh->getCoords();
371 char comp[2*MED_TAILLE_PNOM+1];
372 char unit[2*MED_TAILLE_PNOM+1];
373 std::fill(comp,comp+2*MED_TAILLE_PNOM,' ');
374 comp[2*MED_TAILLE_PNOM]='\0';
376 for(int i=0;i<mesh->getSpaceDimension();i++,work+=3)
378 std::fill(unit,unit+2*MED_TAILLE_PNOM+1,'\0');
379 MEDcoordEcr(fid,maa,mesh->getSpaceDimension(),arr->getPointer(),MED_FULL_INTERLACE,mesh->getNumberOfNodes(),MED_CART,comp,unit);
384 * This method builds the master file 'fileName' of a parallel MED file defined in 'fileNames'.
386 void MEDLoader::writeMasterFile(const char *fileName, const std::vector<std::string>& fileNames, const char *meshName)
388 int nbOfDom=fileNames.size();
389 std::ofstream fs(fileName);
390 fs << "#MED Fichier V 2.3" << " " << std::endl;
391 fs << "#"<<" " << std::endl;
392 fs << nbOfDom <<" " << std::endl;
393 for(int i=0;i<nbOfDom;i++)
394 fs << meshName << " " << i+1 << " " << meshName << "_" << i+1 << " localhost " << fileNames[i] << " " << std::endl;
397 void MEDLoader::writeParaMesh(const char *fileName, ParaMEDMEM::ParaMESH *mesh)
399 if(!mesh->getBlockTopology()->getProcGroup()->containsMyRank())
401 int myRank=mesh->getBlockTopology()->getProcGroup()->myRank();
402 int nbDomains=mesh->getBlockTopology()->getProcGroup()->size();
403 std::vector<std::string> fileNames(nbDomains);
404 for(int i=0;i<nbDomains;i++)
406 std::ostringstream sstr;
407 sstr << fileName << i+1 << ".med";
408 fileNames[i]=sstr.str();
411 writeMasterFile(fileName,fileNames,mesh->getCellMesh()->getName());
412 writeUMesh(fileNames[myRank].c_str(),mesh->getCellMesh());
415 void MEDLoader::writeParaField(const char *fileName, const char *meshName, ParaMEDMEM::ParaFIELD *f)