int GModel::writePLY2(const std::string &name) { FILE *fp = Fopen(name.c_str(), "w"); if(!fp){ Msg::Error("Unable to open file '%s'", name.c_str()); return 0; } int numVertices = indexMeshVertices(true); int numTriangles = 0; for(fiter it = firstFace(); it != lastFace(); ++it){ numTriangles += (*it)->triangles.size(); } fprintf(fp, "%d\n", numVertices); fprintf(fp, "%d\n", numTriangles); std::vector<GEntity*> entities; getEntities(entities); for(unsigned int i = 0; i < entities.size(); i++) for(unsigned int j = 0; j < entities[i]->mesh_vertices.size(); j++) entities[i]->mesh_vertices[j]->writePLY2(fp); for(fiter it = firstFace(); it != lastFace(); ++it){ for(unsigned int i = 0; i < (*it)->triangles.size(); i++) (*it)->triangles[i]->writePLY2(fp); } fclose(fp); return 1; }
int GModel::writeIR3(const std::string &name, int elementTagType, bool saveAll, double scalingFactor) { FILE *fp = Fopen(name.c_str(), "w"); if(!fp){ Msg::Error("Unable to open file '%s'", name.c_str()); return 0; } if(noPhysicalGroups()) saveAll = true; int numVertices = indexMeshVertices(saveAll), num2D = 0, num3D = 0; for(fiter it = firstFace(); it != lastFace(); ++it) if(saveAll || (*it)->physicals.size()) num2D += (*it)->getNumMeshElements(); for(riter it = firstRegion(); it != lastRegion(); ++it) if(saveAll || (*it)->physicals.size()) num3D += (*it)->getNumMeshElements(); fprintf(fp,"33\n"); if(num2D && num3D) fprintf(fp,"%d %d %d\n", numVertices, num2D, num3D); else fprintf(fp,"%d %d\n", numVertices, num2D ? num2D : num3D); std::vector<GEntity*> entities; getEntities(entities); for(unsigned int i = 0; i < entities.size(); i++) for(unsigned int j = 0; j < entities[i]->mesh_vertices.size(); j++) if(entities[i]->mesh_vertices[j]->getIndex() >= 0) fprintf(fp,"%d %.16g %.16g %.16g\n", entities[i]->mesh_vertices[j]->getIndex(), entities[i]->mesh_vertices[j]->x() * scalingFactor, entities[i]->mesh_vertices[j]->y() * scalingFactor, entities[i]->mesh_vertices[j]->z() * scalingFactor); int iElement = 1; for(fiter it = firstFace(); it != lastFace(); ++it){ int numPhys = (*it)->physicals.size(); if(saveAll || numPhys) for(unsigned int i = 0; i < (*it)->getNumMeshElements(); i++) (*it)->getMeshElement(i)->writeIR3 (fp, elementTagType, iElement++, (*it)->tag(), numPhys ? (*it)->physicals[0] : 0); } iElement = 1; for(riter it = firstRegion(); it != lastRegion(); ++it){ int numPhys = (*it)->physicals.size(); if(saveAll || numPhys) for(unsigned int i = 0; i < (*it)->getNumMeshElements(); i++) (*it)->getMeshElement(i)->writeIR3 (fp, elementTagType, iElement++, (*it)->tag(), numPhys ? (*it)->physicals[0] : 0); } fclose(fp); return 1; }
int GModel::writeMAIL(const std::string &name, bool saveAll, double scalingFactor) { // CEA triangulation (.mail format) for Eric Darrigrand. Note that // we currently don't save the edges of the triangulation (the last // part of the file). FILE *fp = Fopen(name.c_str(), "w"); if(!fp){ Msg::Error("Unable to open file '%s'", name.c_str()); return 0; } if(noPhysicalGroups()) saveAll = true; int numVertices = indexMeshVertices(saveAll), numTriangles = 0; for(fiter it = firstFace(); it != lastFace(); ++it) if(saveAll || (*it)->physicals.size()) numTriangles += (*it)->triangles.size(); fprintf(fp, " %d %d\n", numVertices, numTriangles); std::vector<GEntity*> entities; getEntities(entities); for(unsigned int i = 0; i < entities.size(); i++){ for(unsigned int j = 0; j < entities[i]->mesh_vertices.size(); j++){ MVertex *v = entities[i]->mesh_vertices[j]; fprintf(fp, " %19.10E %19.10E %19.10E\n", v->x() * scalingFactor, v->y() * scalingFactor, v->z() * scalingFactor); } } for(fiter it = firstFace(); it != lastFace(); ++it){ if(saveAll || (*it)->physicals.size()){ for(unsigned int i = 0; i < (*it)->triangles.size(); i++){ MTriangle *t = (*it)->triangles[i]; fprintf(fp, " %d %d %d\n", t->getVertex(0)->getIndex(), t->getVertex(1)->getIndex(), t->getVertex(2)->getIndex()); } } } // TODO write edges (with signs) for(fiter it = firstFace(); it != lastFace(); ++it){ if(saveAll || (*it)->physicals.size()){ for(unsigned int i = 0; i < (*it)->triangles.size(); i++){ //MTriangle *t = (*it)->triangles[i]; fprintf(fp, " %d %d %d\n", 0, 0, 0); } } } fclose(fp); return 1; }
int GModel::writeBDF(const std::string &name, int format, int elementTagType, bool saveAll, double scalingFactor) { FILE *fp = Fopen(name.c_str(), "w"); if(!fp){ Msg::Error("Unable to open file '%s'", name.c_str()); return 0; } if(noPhysicalGroups()) saveAll = true; indexMeshVertices(saveAll); fprintf(fp, "$ Created by Gmsh\n"); std::vector<GEntity*> entities; getEntities(entities); // nodes for(unsigned int i = 0; i < entities.size(); i++) for(unsigned int j = 0; j < entities[i]->mesh_vertices.size(); j++) entities[i]->mesh_vertices[j]->writeBDF(fp, format, scalingFactor); // elements for(unsigned int i = 0; i < entities.size(); i++) for(unsigned int j = 0; j < entities[i]->getNumMeshElements(); j++){ int numPhys = entities[i]->physicals.size(); if(saveAll || numPhys) entities[i]->getMeshElement(j)->writeBDF (fp, format, elementTagType, entities[i]->tag(), numPhys ? entities[i]->physicals[0] : 0); } fprintf(fp, "ENDDATA\n"); fclose(fp); return 1; }
int GModel::writeKEY(const std::string &name, int saveAll, int saveGroupsOfNodes, double scalingFactor) { FILE *fp = Fopen(name.c_str(), "w"); if(!fp) { Msg::Error("Unable to open file '%s'", name.c_str()); return 0; } if(noPhysicalGroups()) saveAll = 0x51; indexMeshVertices(saveAll & 0x51); std::vector<GEntity *> entities; getEntities(entities); fprintf(fp, "$# LS-DYNA Keyword file created by Gmsh\n*KEYWORD\n*TITLE\n"); fprintf(fp, " %s\n", name.c_str()); fprintf(fp, "*NODE\n"); for(std::size_t i = 0; i < entities.size(); i++) for(std::size_t j = 0; j < entities[i]->mesh_vertices.size(); j++) entities[i]->mesh_vertices[j]->writeKEY(fp, scalingFactor); if(!(saveAll & 0x2)) // save or ignore Vertex, not in GUI for(viter it = firstVertex(); it != lastVertex(); ++it) { writeElementsKEY(fp, *it, (*it)->points, saveAll & 0x1); } if(!(saveAll & 0x8)) // save or ignore line for(eiter it = firstEdge(); it != lastEdge(); ++it) { writeElementsKEY(fp, *it, (*it)->lines, saveAll & 0x4); } if(!(saveAll & 0x20)) // save or ignore surface for(fiter it = firstFace(); it != lastFace(); ++it) { writeElementsKEY(fp, *it, (*it)->triangles, saveAll & 0x10); writeElementsKEY(fp, *it, (*it)->quadrangles, saveAll & 0x10); } if(!(saveAll & 0x80)) // save or ignore surface for(riter it = firstRegion(); it != lastRegion(); ++it) { writeElementsKEY(fp, *it, (*it)->tetrahedra, saveAll & 0x40); writeElementsKEY(fp, *it, (*it)->hexahedra, saveAll & 0x40); writeElementsKEY(fp, *it, (*it)->prisms, saveAll & 0x40); writeElementsKEY(fp, *it, (*it)->pyramids, saveAll & 0x40); } std::map<int, std::vector<GEntity *> > groups[4]; getPhysicalGroups(groups); int setid = 0; // save elements sets for each physical group if(saveGroupsOfNodes & 0x2) { for(int dim = 0; dim <= 3; dim++) { if(saveAll & (0x2 << (2 * dim))) continue; // elements are ignored for(std::map<int, std::vector<GEntity *> >::iterator it = groups[dim].begin(); it != groups[dim].end(); it++) { std::vector<GEntity *> &entities = it->second; int n = 0; for(std::size_t i = 0; i < entities.size(); i++) { for(std::size_t j = 0; j < entities[i]->getNumMeshElements(); j++) { MElement *e = entities[i]->getMeshElement(j); if(!n) { const char *str = (e->getDim() == 3) ? "SOLID" : (e->getDim() == 2) ? "SHELL" : (e->getDim() == 1) ? "BEAM" : "NODE"; fprintf(fp, "*SET_%s_LIST\n$# %s\n%d", str, physicalName(this, dim, it->first).c_str(), ++setid); } if(!(n % 8)) fprintf(fp, "\n%lu", e->getNum()); else fprintf(fp, ", %lu", e->getNum()); n++; } } if(n) fprintf(fp, "\n"); } } } // save node sets for each physical group, for easier load/b.c. if(saveGroupsOfNodes & 0x1) { for(int dim = 1; dim <= 3; dim++) { for(std::map<int, std::vector<GEntity *> >::iterator it = groups[dim].begin(); it != groups[dim].end(); it++) { std::set<MVertex *> nodes; std::vector<GEntity *> &entities = it->second; for(std::size_t i = 0; i < entities.size(); i++) { for(std::size_t j = 0; j < entities[i]->getNumMeshElements(); j++) { MElement *e = entities[i]->getMeshElement(j); for(std::size_t k = 0; k < e->getNumVertices(); k++) nodes.insert(e->getVertex(k)); } } fprintf(fp, "*SET_NODE_LIST\n$# %s\n%d", physicalName(this, dim, it->first).c_str(), ++setid); int n = 0; for(std::set<MVertex *>::iterator it2 = nodes.begin(); it2 != nodes.end(); it2++) { if(!(n % 8)) fprintf(fp, "\n%ld", (*it2)->getIndex()); else fprintf(fp, ", %ld", (*it2)->getIndex()); n++; } if(n) fprintf(fp, "\n"); } } } fprintf(fp, "*END\n"); fclose(fp); return 1; }
int GModel::writeDIFF(const std::string &name, bool binary, bool saveAll, double scalingFactor) { if(binary){ Msg::Error("Binary DIFF output is not implemented"); return 0; } FILE *fp = Fopen(name.c_str(), binary ? "wb" : "w"); if(!fp){ Msg::Error("Unable to open file '%s'", name.c_str()); return 0; } if(noPhysicalGroups()) saveAll = true; // get the number of vertices and index the vertices in a continuous // sequence int numVertices = indexMeshVertices(saveAll); // tag the vertices according to which surface they belong to (Note // that we use a brute force approach here, so that we can deal with // models with incomplete topology. For example, when we merge 2 STL // triangulations we don't have the boundary information between the // faces, and the vertices would end up categorized on either one.) std::vector<std::list<int> > vertexTags(numVertices); std::list<int> boundaryIndicators; for(riter it = firstRegion(); it != lastRegion(); it++){ std::list<GFace*> faces = (*it)->faces(); for(std::list<GFace*>::iterator itf = faces.begin(); itf != faces.end(); itf++){ GFace *gf = *itf; boundaryIndicators.push_back(gf->tag()); for(unsigned int i = 0; i < gf->getNumMeshElements(); i++){ MElement *e = gf->getMeshElement(i); for(int j = 0; j < e->getNumVertices(); j++){ MVertex *v = e->getVertex(j); if(v->getIndex() > 0) vertexTags[v->getIndex() - 1].push_back(gf->tag()); } } } } boundaryIndicators.sort(); boundaryIndicators.unique(); for(int i = 0; i < numVertices; i++){ vertexTags[i].sort(); vertexTags[i].unique(); } // get all the entities in the model std::vector<GEntity*> entities; getEntities(entities); // find max dimension of mesh elements we need to save int dim = 0; for(unsigned int i = 0; i < entities.size(); i++) if(entities[i]->physicals.size() || saveAll) for(unsigned int j = 0; j < entities[i]->getNumMeshElements(); j++) dim = std::max(dim, entities[i]->getMeshElement(j)->getDim()); // loop over all elements we need to save int numElements = 0, maxNumNodesPerElement = 0; for(unsigned int i = 0; i < entities.size(); i++){ if(entities[i]->physicals.size() || saveAll){ for(unsigned int j = 0; j < entities[i]->getNumMeshElements(); j++){ MElement *e = entities[i]->getMeshElement(j); if(e->getStringForDIFF() && e->getDim() == dim){ numElements++; maxNumNodesPerElement = std::max(maxNumNodesPerElement, e->getNumVertices()); } } } } fprintf(fp, "\n\n"); fprintf(fp, " Finite element mesh (GridFE):\n\n"); fprintf(fp, " Number of space dim. = 3\n"); fprintf(fp, " Number of elements = %d\n", numElements); fprintf(fp, " Number of nodes = %d\n\n", numVertices); fprintf(fp, " All elements are of the same type : dpTRUE\n"); fprintf(fp, " Max number of nodes in an element: %d \n", maxNumNodesPerElement); fprintf(fp, " Only one subdomain : dpFALSE\n"); fprintf(fp, " Lattice data ? 0\n\n\n\n"); fprintf(fp, " %d Boundary indicators: ", (int)boundaryIndicators.size()); for(std::list<int>::iterator it = boundaryIndicators.begin(); it != boundaryIndicators.end(); it++) fprintf(fp, " %d", *it); fprintf(fp, "\n\n\n"); fprintf(fp," Nodal coordinates and nodal boundary indicators,\n"); fprintf(fp," the columns contain:\n"); fprintf(fp," - node number\n"); fprintf(fp," - coordinates\n"); fprintf(fp," - no of boundary indicators that are set (ON)\n"); fprintf(fp," - the boundary indicators that are set (ON) if any.\n"); fprintf(fp,"#\n"); // write mesh vertices for(unsigned int i = 0; i < entities.size(); i++){ for(unsigned int j = 0; j < entities[i]->mesh_vertices.size(); j++){ MVertex *v = entities[i]->mesh_vertices[j]; if(v->getIndex() > 0){ v->writeDIFF(fp, binary, scalingFactor); fprintf(fp, " [%d] ", (int)vertexTags[v->getIndex() - 1].size()); for(std::list<int>::iterator it = vertexTags[v->getIndex() - 1].begin(); it != vertexTags[v->getIndex() - 1].end(); it++) fprintf(fp," %d ", *it); fprintf(fp,"\n"); } } } fprintf(fp, "\n"); fprintf(fp, "\n"); fprintf(fp, " Element types and connectivity\n"); fprintf(fp, " the columns contain:\n"); fprintf(fp, " - element number\n"); fprintf(fp, " - element type\n"); fprintf(fp, " - subdomain number \n"); fprintf(fp, " - the global node numbers of the nodes in the element.\n"); fprintf(fp, "#\n"); // write mesh elements int num = 0; for(unsigned int i = 0; i < entities.size(); i++){ if(entities[i]->physicals.size() || saveAll){ for(unsigned int j = 0; j < entities[i]->getNumMeshElements(); j++){ MElement *e = entities[i]->getMeshElement(j); if(e->getStringForDIFF() && e->getDim() == dim) e->writeDIFF(fp, ++num, binary, entities[i]->tag()); } } } fprintf(fp, "\n"); fclose(fp); return 1; }
int GModel::writeMESH(const std::string &name, int elementTagType, bool saveAll, double scalingFactor) { FILE *fp = Fopen(name.c_str(), "w"); if(!fp){ Msg::Error("Unable to open file '%s'", name.c_str()); return 0; } if(noPhysicalGroups()) saveAll = true; int numVertices = indexMeshVertices(saveAll); fprintf(fp, " MeshVersionFormatted 2\n"); fprintf(fp, " Dimension\n"); fprintf(fp, " 3\n"); fprintf(fp, " Vertices\n"); fprintf(fp, " %d\n", numVertices); std::vector<GEntity*> entities; getEntities(entities); for(unsigned int i = 0; i < entities.size(); i++) for(unsigned int j = 0; j < entities[i]->mesh_vertices.size(); j++) entities[i]->mesh_vertices[j]->writeMESH(fp, scalingFactor); int numEdges = 0, numTriangles = 0, numQuadrangles = 0; int numTetrahedra = 0, numHexahedra = 0; for(eiter it = firstEdge(); it != lastEdge(); ++it){ if(saveAll || (*it)->physicals.size()){ numEdges += (*it)->lines.size(); } } for(fiter it = firstFace(); it != lastFace(); ++it){ if(saveAll || (*it)->physicals.size()){ numTriangles += (*it)->triangles.size(); numQuadrangles += (*it)->quadrangles.size(); } } for(riter it = firstRegion(); it != lastRegion(); ++it){ if(saveAll || (*it)->physicals.size()){ numTetrahedra += (*it)->tetrahedra.size(); numHexahedra += (*it)->hexahedra.size(); } } if(numEdges){ if(CTX::instance()->mesh.order == 2) fprintf(fp, " EdgesP2\n"); else fprintf(fp, " Edges\n"); fprintf(fp, " %d\n", numEdges); for(eiter it = firstEdge(); it != lastEdge(); ++it){ int numPhys = (*it)->physicals.size(); if(saveAll || numPhys){ for(unsigned int i = 0; i < (*it)->lines.size(); i++) (*it)->lines[i]->writeMESH(fp, elementTagType, (*it)->tag(), numPhys ? (*it)->physicals[0] : 0); } } } if(numTriangles){ if(CTX::instance()->mesh.order == 2) fprintf(fp, " TrianglesP2\n"); else fprintf(fp, " Triangles\n"); fprintf(fp, " %d\n", numTriangles); for(fiter it = firstFace(); it != lastFace(); ++it){ int numPhys = (*it)->physicals.size(); if(saveAll || numPhys){ for(unsigned int i = 0; i < (*it)->triangles.size(); i++) (*it)->triangles[i]->writeMESH(fp, elementTagType, (*it)->tag(), numPhys ? (*it)->physicals[0] : 0); } } } if(numQuadrangles){ fprintf(fp, " Quadrilaterals\n"); fprintf(fp, " %d\n", numQuadrangles); for(fiter it = firstFace(); it != lastFace(); ++it){ int numPhys = (*it)->physicals.size(); if(saveAll || numPhys){ for(unsigned int i = 0; i < (*it)->quadrangles.size(); i++) (*it)->quadrangles[i]->writeMESH(fp, elementTagType, (*it)->tag(), numPhys ? (*it)->physicals[0] : 0); } } } if(numTetrahedra){ if(CTX::instance()->mesh.order == 2) fprintf(fp, " TetrahedraP2\n"); else fprintf(fp, " Tetrahedra\n"); fprintf(fp, " %d\n", numTetrahedra); for(riter it = firstRegion(); it != lastRegion(); ++it){ int numPhys = (*it)->physicals.size(); if(saveAll || numPhys){ for(unsigned int i = 0; i < (*it)->tetrahedra.size(); i++) (*it)->tetrahedra[i]->writeMESH(fp, elementTagType, (*it)->tag(), numPhys ? (*it)->physicals[0] : 0); } } } if(numHexahedra){ fprintf(fp, " Hexahedra\n"); fprintf(fp, " %d\n", numHexahedra); for(riter it = firstRegion(); it != lastRegion(); ++it){ int numPhys = (*it)->physicals.size(); if(saveAll || numPhys){ for(unsigned int i = 0; i < (*it)->hexahedra.size(); i++) (*it)->hexahedra[i]->writeMESH(fp, elementTagType, (*it)->tag(), numPhys ? (*it)->physicals[0] : 0); } } } fprintf(fp, " End\n"); fclose(fp); return 1; }
int GModel::readMED(const std::string &name) { med_idt fid = MEDouvrir((char*)name.c_str(), MED_LECTURE); if(fid < 0) { Msg::Error("Unable to open file '%s'", name.c_str()); return 0; } med_int v[3], vf[3]; MEDversionDonner(&v[0], &v[1], &v[2]); MEDversionLire(fid, &vf[0], &vf[1], &vf[2]); Msg::Info("Reading MED file V%d.%d.%d using MED library V%d.%d.%d", vf[0], vf[1], vf[2], v[0], v[1], v[2]); if(vf[0] < 2 || (vf[0] == 2 && vf[1] < 2)){ Msg::Error("Cannot read MED file older than V2.2"); return 0; } std::vector<std::string> meshNames; for(int i = 0; i < MEDnMaa(fid); i++){ char meshName[MED_TAILLE_NOM + 1], meshDesc[MED_TAILLE_DESC + 1]; med_int spaceDim; med_maillage meshType; #if (MED_MAJOR_NUM == 3) med_int meshDim, nStep; char dtUnit[MED_SNAME_SIZE + 1]; char axisName[3 * MED_SNAME_SIZE + 1], axisUnit[3 * MED_SNAME_SIZE + 1]; med_sorting_type sortingType; med_axis_type axisType; if(MEDmeshInfo(fid, i + 1, meshName, &spaceDim, &meshDim, &meshType, meshDesc, dtUnit, &sortingType, &nStep, &axisType, axisName, axisUnit) < 0){ #else if(MEDmaaInfo(fid, i + 1, meshName, &spaceDim, &meshType, meshDesc) < 0){ #endif Msg::Error("Unable to read mesh information"); return 0; } meshNames.push_back(meshName); } if(MEDfermer(fid) < 0){ Msg::Error("Unable to close file '%s'", (char*)name.c_str()); return 0; } int ret = 1; for(unsigned int i = 0; i < meshNames.size(); i++){ // we use the filename as a kind of "partition" indicator, allowing to // complete a model part by part (used e.g. in DDM, since MED does not store // a partition index) GModel *m = findByName(meshNames[i], name); if(!m) m = new GModel(meshNames[i]); ret = m->readMED(name, i); if(!ret) return 0; } return ret; } int GModel::readMED(const std::string &name, int meshIndex) { med_idt fid = MEDouvrir((char*)name.c_str(), MED_LECTURE); if(fid < 0){ Msg::Error("Unable to open file '%s'", name.c_str()); return 0; } int numMeshes = MEDnMaa(fid); if(meshIndex >= numMeshes){ Msg::Info("Could not find mesh %d in MED file", meshIndex); return 0; } checkPointMaxNumbers(); GModel::setCurrent(this); // make sure we increment max nums in this model // read mesh info char meshName[MED_TAILLE_NOM + 1], meshDesc[MED_TAILLE_DESC + 1]; med_int spaceDim, nStep = 1; med_maillage meshType; #if (MED_MAJOR_NUM == 3) med_int meshDim; char dtUnit[MED_SNAME_SIZE + 1]; char axisName[3 * MED_SNAME_SIZE + 1], axisUnit[3 * MED_SNAME_SIZE + 1]; med_sorting_type sortingType; med_axis_type axisType; if(MEDmeshInfo(fid, meshIndex + 1, meshName, &spaceDim, &meshDim, &meshType, meshDesc, dtUnit, &sortingType, &nStep, &axisType, axisName, axisUnit) < 0){ #else if(MEDmaaInfo(fid, meshIndex + 1, meshName, &spaceDim, &meshType, meshDesc) < 0){ #endif Msg::Error("Unable to read mesh information"); return 0; } // FIXME: we should support multi-step MED3 meshes (probably by // storing each mesh as a separate model, with a naming convention // e.g. meshName_step%d). This way we could also handle multi-mesh // time sequences in MED3. if(nStep > 1) Msg::Warning("Discarding %d last meshes in multi-step MED mesh", nStep - 1); setName(meshName); setFileName(name); if(meshType == MED_NON_STRUCTURE){ Msg::Info("Reading %d-D unstructured mesh <<%s>>", spaceDim, meshName); } else{ Msg::Error("Reading structured MED meshes is not supported"); return 0; } med_int vf[3]; MEDversionLire(fid, &vf[0], &vf[1], &vf[2]); // read nodes #if (MED_MAJOR_NUM == 3) med_bool changeOfCoord, geoTransform; med_int numNodes = MEDmeshnEntity(fid, meshName, MED_NO_DT, MED_NO_IT, MED_NODE, MED_NO_GEOTYPE, MED_COORDINATE, MED_NO_CMODE, &changeOfCoord, &geoTransform); #else med_int numNodes = MEDnEntMaa(fid, meshName, MED_COOR, MED_NOEUD, MED_NONE, MED_NOD); #endif if(numNodes < 0){ Msg::Error("Could not read number of MED nodes"); return 0; } if(numNodes == 0){ Msg::Error("No nodes in MED mesh"); return 0; } std::vector<MVertex*> verts(numNodes); std::vector<med_float> coord(spaceDim * numNodes); #if (MED_MAJOR_NUM == 3) if(MEDmeshNodeCoordinateRd(fid, meshName, MED_NO_DT, MED_NO_IT, MED_FULL_INTERLACE, &coord[0]) < 0){ #else std::vector<char> coordName(spaceDim * MED_TAILLE_PNOM + 1); std::vector<char> coordUnit(spaceDim * MED_TAILLE_PNOM + 1); med_repere rep; if(MEDcoordLire(fid, meshName, spaceDim, &coord[0], MED_FULL_INTERLACE, MED_ALL, 0, 0, &rep, &coordName[0], &coordUnit[0]) < 0){ #endif Msg::Error("Could not read MED node coordinates"); return 0; } std::vector<med_int> nodeTags(numNodes); #if (MED_MAJOR_NUM == 3) if(MEDmeshEntityNumberRd(fid, meshName, MED_NO_DT, MED_NO_IT, MED_NODE, MED_NO_GEOTYPE, &nodeTags[0]) < 0) #else if(MEDnumLire(fid, meshName, &nodeTags[0], numNodes, MED_NOEUD, MED_NONE) < 0) #endif nodeTags.clear(); for(int i = 0; i < numNodes; i++) verts[i] = new MVertex(coord[spaceDim * i], (spaceDim > 1) ? coord[spaceDim * i + 1] : 0., (spaceDim > 2) ? coord[spaceDim * i + 2] : 0., 0, nodeTags.empty() ? 0 : nodeTags[i]); // read elements (loop over all possible MSH element types) for(int mshType = 0; mshType < MSH_NUM_TYPE; mshType++){ med_geometrie_element type = msh2medElementType(mshType); if(type == MED_NONE) continue; #if (MED_MAJOR_NUM == 3) med_bool changeOfCoord; med_bool geoTransform; med_int numEle = MEDmeshnEntity(fid, meshName, MED_NO_DT, MED_NO_IT, MED_CELL, type, MED_CONNECTIVITY, MED_NODAL, &changeOfCoord, &geoTransform); #else med_int numEle = MEDnEntMaa(fid, meshName, MED_CONN, MED_MAILLE, type, MED_NOD); #endif if(numEle <= 0) continue; int numNodPerEle = type % 100; std::vector<med_int> conn(numEle * numNodPerEle); #if (MED_MAJOR_NUM == 3) if(MEDmeshElementConnectivityRd(fid, meshName, MED_NO_DT, MED_NO_IT, MED_CELL, type, MED_NODAL, MED_FULL_INTERLACE, &conn[0]) < 0){ #else if(MEDconnLire(fid, meshName, spaceDim, &conn[0], MED_FULL_INTERLACE, 0, MED_ALL, MED_MAILLE, type, MED_NOD) < 0){ #endif Msg::Error("Could not read MED elements"); return 0; } std::vector<med_int> fam(numEle, 0); #if (MED_MAJOR_NUM == 3) if(MEDmeshEntityFamilyNumberRd(fid, meshName, MED_NO_DT, MED_NO_IT, MED_CELL, type, &fam[0]) < 0){ #else if(MEDfamLire(fid, meshName, &fam[0], numEle, MED_MAILLE, type) < 0){ #endif Msg::Info("No family number for elements: using 0 as default family number"); } std::vector<med_int> eleTags(numEle); #if (MED_MAJOR_NUM == 3) if(MEDmeshEntityNumberRd(fid, meshName, MED_NO_DT, MED_NO_IT, MED_CELL, type, &eleTags[0]) < 0) #else if(MEDnumLire(fid, meshName, &eleTags[0], numEle, MED_MAILLE, type) < 0) #endif eleTags.clear(); std::map<int, std::vector<MElement*> > elements; MElementFactory factory; for(int j = 0; j < numEle; j++){ std::vector<MVertex*> v(numNodPerEle); for(int k = 0; k < numNodPerEle; k++) v[k] = verts[conn[numNodPerEle * j + med2mshNodeIndex(type, k)] - 1]; MElement *e = factory.create(mshType, v, eleTags.empty() ? 0 : eleTags[j]); if(e) elements[-fam[j]].push_back(e); } _storeElementsInEntities(elements); } _associateEntityWithMeshVertices(); _storeVerticesInEntities(verts); // read family info med_int numFamilies = MEDnFam(fid, meshName); if(numFamilies < 0){ Msg::Error("Could not read MED families"); return 0; } for(int i = 0; i < numFamilies; i++){ #if (MED_MAJOR_NUM == 3) med_int numAttrib = (vf[0] == 2) ? MEDnFamily23Attribute(fid, meshName, i + 1) : 0; med_int numGroups = MEDnFamilyGroup(fid, meshName, i + 1); #else med_int numAttrib = MEDnAttribut(fid, meshName, i + 1); med_int numGroups = MEDnGroupe(fid, meshName, i + 1); #endif if(numAttrib < 0 || numGroups < 0){ Msg::Error("Could not read MED groups or attributes"); return 0; } std::vector<med_int> attribId(numAttrib + 1); std::vector<med_int> attribVal(numAttrib + 1); std::vector<char> attribDes(MED_TAILLE_DESC * numAttrib + 1); std::vector<char> groupNames(MED_TAILLE_LNOM * numGroups + 1); char familyName[MED_TAILLE_NOM + 1]; med_int familyNum; #if (MED_MAJOR_NUM == 3) if(vf[0] == 2){ // MED2 file if(MEDfamily23Info(fid, meshName, i + 1, familyName, &attribId[0], &attribVal[0], &attribDes[0], &familyNum, &groupNames[0]) < 0){ Msg::Error("Could not read info for MED2 family %d", i + 1); continue; } } else{ if(MEDfamilyInfo(fid, meshName, i + 1, familyName, &familyNum, &groupNames[0]) < 0){ Msg::Error("Could not read info for MED3 family %d", i + 1); continue; } } #else if(MEDfamInfo(fid, meshName, i + 1, familyName, &familyNum, &attribId[0], &attribVal[0], &attribDes[0], &numAttrib, &groupNames[0], &numGroups) < 0){ Msg::Error("Could not read info for MED family %d", i + 1); continue; } #endif // family tags are unique (for all dimensions) GEntity *ge; if((ge = getRegionByTag(-familyNum))){} else if((ge = getFaceByTag(-familyNum))){} else if((ge = getEdgeByTag(-familyNum))){} else ge = getVertexByTag(-familyNum); if(ge){ elementaryNames[std::pair<int, int>(ge->dim(), -familyNum)] = familyName; if(numGroups > 0){ for(int j = 0; j < numGroups; j++){ char tmp[MED_TAILLE_LNOM + 1]; strncpy(tmp, &groupNames[j * MED_TAILLE_LNOM], MED_TAILLE_LNOM); tmp[MED_TAILLE_LNOM] = '\0'; // don't use same physical number across dimensions, as e.g. getdp // does not support this int pnum = setPhysicalName(tmp, ge->dim(), getMaxPhysicalNumber(-1) + 1); if(std::find(ge->physicals.begin(), ge->physicals.end(), pnum) == ge->physicals.end()) ge->physicals.push_back(pnum); } } } } // check if we need to read some post-processing data later #if (MED_MAJOR_NUM == 3) bool postpro = (MEDnField(fid) > 0) ? true : false; #else bool postpro = (MEDnChamp(fid, 0) > 0) ? true : false; #endif if(MEDfermer(fid) < 0){ Msg::Error("Unable to close file '%s'", (char*)name.c_str()); return 0; } return postpro ? 2 : 1; } template<class T> static void fillElementsMED(med_int family, std::vector<T*> &elements, std::vector<med_int> &conn, std::vector<med_int> &fam, med_geometrie_element &type) { if(elements.empty()) return; type = msh2medElementType(elements[0]->getTypeForMSH()); if(type == MED_NONE){ Msg::Warning("Unsupported element type in MED format"); return; } for(unsigned int i = 0; i < elements.size(); i++){ elements[i]->setVolumePositive(); for(int j = 0; j < elements[i]->getNumVertices(); j++) conn.push_back(elements[i]->getVertex(med2mshNodeIndex(type, j))->getIndex()); fam.push_back(family); } } static void writeElementsMED(med_idt &fid, char *meshName, std::vector<med_int> &conn, std::vector<med_int> &fam, med_geometrie_element type) { if(fam.empty()) return; #if (MED_MAJOR_NUM == 3) if(MEDmeshElementWr(fid, meshName, MED_NO_DT, MED_NO_IT, 0., MED_CELL, type, MED_NODAL, MED_FULL_INTERLACE, (med_int)fam.size(), &conn[0], MED_FALSE, 0, MED_FALSE, 0, MED_TRUE, &fam[0]) < 0) #else if(MEDelementsEcr(fid, meshName, (med_int)3, &conn[0], MED_FULL_INTERLACE, 0, MED_FAUX, 0, MED_FAUX, &fam[0], (med_int)fam.size(), MED_MAILLE, type, MED_NOD) < 0) #endif Msg::Error("Could not write MED elements"); } int GModel::writeMED(const std::string &name, bool saveAll, double scalingFactor) { med_idt fid = MEDouvrir((char*)name.c_str(), MED_CREATION); if(fid < 0){ Msg::Error("Unable to open file '%s'", name.c_str()); return 0; } // write header if(MEDfichDesEcr(fid, (char*)"MED file generated by Gmsh") < 0){ Msg::Error("Unable to write MED descriptor"); return 0; } char *meshName = (char*)getName().c_str(); // Gmsh always writes 3D unstructured meshes #if (MED_MAJOR_NUM == 3) char dtUnit[MED_SNAME_SIZE + 1] = ""; char axisName[3 * MED_SNAME_SIZE + 1] = ""; char axisUnit[3 * MED_SNAME_SIZE + 1] = ""; if(MEDmeshCr(fid, meshName, 3, 3, MED_UNSTRUCTURED_MESH, "Mesh created with Gmsh", dtUnit, MED_SORT_DTIT, MED_CARTESIAN, axisName, axisUnit) < 0){ #else if(MEDmaaCr(fid, meshName, 3, MED_NON_STRUCTURE, (char*)"Mesh created with Gmsh") < 0){ #endif Msg::Error("Could not create MED mesh"); return 0; } // if there are no physicals we save all the elements if(noPhysicalGroups()) saveAll = true; // index the vertices we save in a continuous sequence (MED // connectivity is given in terms of vertex indices) indexMeshVertices(saveAll); // get a vector containing all the geometrical entities in the // model (the ordering of the entities must be the same as the one // used during the indexing of the vertices) std::vector<GEntity*> entities; getEntities(entities); std::map<GEntity*, int> families; // write the families { // always create a "0" family, with no groups or attributes #if (MED_MAJOR_NUM == 3) if(MEDfamilyCr(fid, meshName, "F_0", 0, 0, "") < 0) #else if(MEDfamCr(fid, meshName, (char*)"F_0", 0, 0, 0, 0, 0, 0, 0) < 0) #endif Msg::Error("Could not create MED family 0"); // create one family per elementary entity, with one group per // physical entity and no attributes for(unsigned int i = 0; i < entities.size(); i++){ if(saveAll || entities[i]->physicals.size()){ int num = - ((int)families.size() + 1); families[entities[i]] = num; std::ostringstream fs; fs << entities[i]->dim() << "D_" << entities[i]->tag(); std::string familyName = "F_" + fs.str(); std::string groupName; for(unsigned j = 0; j < entities[i]->physicals.size(); j++){ std::string tmp = getPhysicalName (entities[i]->dim(), entities[i]->physicals[j]); if(tmp.empty()){ // create unique name std::ostringstream gs; gs << entities[i]->dim() << "D_" << entities[i]->physicals[j]; groupName += "G_" + gs.str(); } else groupName += tmp; groupName.resize((j + 1) * MED_TAILLE_LNOM, ' '); } #if (MED_MAJOR_NUM == 3) if(MEDfamilyCr(fid, meshName, familyName.c_str(), (med_int)num, (med_int)entities[i]->physicals.size(), groupName.c_str()) < 0) #else if(MEDfamCr(fid, meshName, (char*)familyName.c_str(), (med_int)num, 0, 0, 0, 0, (char*)groupName.c_str(), (med_int)entities[i]->physicals.size()) < 0) #endif Msg::Error("Could not create MED family %d", num); } } } // write the nodes { std::vector<med_float> coord; std::vector<med_int> fam; for(unsigned int i = 0; i < entities.size(); i++){ for(unsigned int j = 0; j < entities[i]->mesh_vertices.size(); j++){ MVertex *v = entities[i]->mesh_vertices[j]; if(v->getIndex() >= 0){ coord.push_back(v->x() * scalingFactor); coord.push_back(v->y() * scalingFactor); coord.push_back(v->z() * scalingFactor); fam.push_back(0); // we never create node families } } } if(fam.empty()){ Msg::Error("No nodes to write in MED mesh"); return 0; } #if (MED_MAJOR_NUM == 3) if(MEDmeshNodeWr(fid, meshName, MED_NO_DT, MED_NO_IT, 0., MED_FULL_INTERLACE, (med_int)fam.size(), &coord[0], MED_FALSE, "", MED_FALSE, 0, MED_TRUE, &fam[0]) < 0) #else char coordName[3 * MED_TAILLE_PNOM + 1] = "x y z "; char coordUnit[3 * MED_TAILLE_PNOM + 1] = "unknown unknown unknown "; if(MEDnoeudsEcr(fid, meshName, (med_int)3, &coord[0], MED_FULL_INTERLACE, MED_CART, coordName, coordUnit, 0, MED_FAUX, 0, MED_FAUX, &fam[0], (med_int)fam.size()) < 0) #endif Msg::Error("Could not write nodes"); } // write the elements { { // points med_geometrie_element typ = MED_NONE; std::vector<med_int> conn, fam; for(viter it = firstVertex(); it != lastVertex(); it++) if(saveAll || (*it)->physicals.size()) fillElementsMED(families[*it], (*it)->points, conn, fam, typ); writeElementsMED(fid, meshName, conn, fam, typ); } { // lines med_geometrie_element typ = MED_NONE; std::vector<med_int> conn, fam; for(eiter it = firstEdge(); it != lastEdge(); it++) if(saveAll || (*it)->physicals.size()) fillElementsMED(families[*it], (*it)->lines, conn, fam, typ); writeElementsMED(fid, meshName, conn, fam, typ); } { // triangles med_geometrie_element typ = MED_NONE; std::vector<med_int> conn, fam; for(fiter it = firstFace(); it != lastFace(); it++) if(saveAll || (*it)->physicals.size()) fillElementsMED(families[*it], (*it)->triangles, conn, fam, typ); writeElementsMED(fid, meshName, conn, fam, typ); } { // quads med_geometrie_element typ = MED_NONE; std::vector<med_int> conn, fam; for(fiter it = firstFace(); it != lastFace(); it++) if(saveAll || (*it)->physicals.size()) fillElementsMED(families[*it], (*it)->quadrangles, conn, fam, typ); writeElementsMED(fid, meshName, conn, fam, typ); } { // tets med_geometrie_element typ = MED_NONE; std::vector<med_int> conn, fam; for(riter it = firstRegion(); it != lastRegion(); it++) if(saveAll || (*it)->physicals.size()) fillElementsMED(families[*it], (*it)->tetrahedra, conn, fam, typ); writeElementsMED(fid, meshName, conn, fam, typ); } { // hexas med_geometrie_element typ = MED_NONE; std::vector<med_int> conn, fam; for(riter it = firstRegion(); it != lastRegion(); it++) if(saveAll || (*it)->physicals.size()) fillElementsMED(families[*it], (*it)->hexahedra, conn, fam, typ); writeElementsMED(fid, meshName, conn, fam, typ); } { // prisms med_geometrie_element typ = MED_NONE; std::vector<med_int> conn, fam; for(riter it = firstRegion(); it != lastRegion(); it++) if(saveAll || (*it)->physicals.size()) fillElementsMED(families[*it], (*it)->prisms, conn, fam, typ); writeElementsMED(fid, meshName, conn, fam, typ); } { // pyramids med_geometrie_element typ = MED_NONE; std::vector<med_int> conn, fam; for(riter it = firstRegion(); it != lastRegion(); it++) if(saveAll || (*it)->physicals.size()) fillElementsMED(families[*it], (*it)->pyramids, conn, fam, typ); writeElementsMED(fid, meshName, conn, fam, typ); } } if(MEDfermer(fid) < 0){ Msg::Error("Unable to close file '%s'", (char*)name.c_str()); return 0; } return 1; } #else int GModel::readMED(const std::string &name) { Msg::Error("Gmsh must be compiled with MED support to read '%s'", name.c_str()); return 0; }
int GModel::writeINP(const std::string &name, bool saveAll, bool saveGroupsOfNodes, double scalingFactor) { FILE *fp = Fopen(name.c_str(), "w"); if(!fp){ Msg::Error("Unable to open file '%s'", name.c_str()); return 0; } if(noPhysicalGroups()) saveAll = true; indexMeshVertices(saveAll); std::vector<GEntity*> entities; getEntities(entities); fprintf(fp, "*Heading\n"); fprintf(fp, " %s\n", name.c_str()); fprintf(fp, "*Node\n"); for(unsigned int i = 0; i < entities.size(); i++) for(unsigned int j = 0; j < entities[i]->mesh_vertices.size(); j++) entities[i]->mesh_vertices[j]->writeINP(fp, scalingFactor); for(viter it = firstVertex(); it != lastVertex(); ++it){ writeElementsINP(fp, *it, (*it)->points, saveAll); } for(eiter it = firstEdge(); it != lastEdge(); ++it){ writeElementsINP(fp, *it, (*it)->lines, saveAll); } for(fiter it = firstFace(); it != lastFace(); ++it){ writeElementsINP(fp, *it, (*it)->triangles, saveAll); writeElementsINP(fp, *it, (*it)->quadrangles, saveAll); } for(riter it = firstRegion(); it != lastRegion(); ++it){ writeElementsINP(fp, *it, (*it)->tetrahedra, saveAll); writeElementsINP(fp, *it, (*it)->hexahedra, saveAll); writeElementsINP(fp, *it, (*it)->prisms, saveAll); writeElementsINP(fp, *it, (*it)->pyramids, saveAll); } std::map<int, std::vector<GEntity*> > groups[4]; getPhysicalGroups(groups); // save elements sets for each physical group for(int dim = 0; dim <= 3; dim++){ for(std::map<int, std::vector<GEntity*> >::iterator it = groups[dim].begin(); it != groups[dim].end(); it++){ std::vector<GEntity *> &entities = it->second; fprintf(fp, "*ELSET,ELSET=%s\n", physicalName(this, dim, it->first).c_str()); int n = 0; for(unsigned int i = 0; i < entities.size(); i++){ for(unsigned int j = 0; j < entities[i]->getNumMeshElements(); j++){ MElement *e = entities[i]->getMeshElement(j); if(n && !(n % 10)) fprintf(fp, "\n"); fprintf(fp, "%d, ", e->getNum()); n++; } } fprintf(fp, "\n"); } } // save node sets for each physical group if(saveGroupsOfNodes){ for(int dim = 1; dim <= 3; dim++){ for(std::map<int, std::vector<GEntity*> >::iterator it = groups[dim].begin(); it != groups[dim].end(); it++){ std::set<MVertex*> nodes; std::vector<GEntity *> &entities = it->second; for(unsigned int i = 0; i < entities.size(); i++){ for(unsigned int j = 0; j < entities[i]->getNumMeshElements(); j++){ MElement *e = entities[i]->getMeshElement(j); for (int k = 0; k < e->getNumVertices(); k++) nodes.insert(e->getVertex(k)); } } fprintf(fp, "*NSET,NSET=%s\n", physicalName(this, dim, it->first).c_str()); int n = 0; for(std::set<MVertex*>::iterator it2 = nodes.begin(); it2 != nodes.end(); it2++){ if(n && !(n % 10)) fprintf(fp, "\n"); fprintf(fp, "%d, ", (*it2)->getIndex()); n++; } fprintf(fp, "\n"); } } } fclose(fp); return 1; }
int GModel::writeSU2(const std::string &name, bool saveAll, double scalingFactor) { FILE *fp = Fopen(name.c_str(), "w"); if(!fp){ Msg::Error("Unable to open file '%s'", name.c_str()); return 0; } int ndime = getDim(); if(ndime != 2 && ndime != 3){ Msg::Error("SU2 mesh output valid only for 2D or 3D models (not %dD)", ndime); fclose(fp); return 0; } if(noPhysicalGroups()) saveAll = true; fprintf(fp, "NDIME= %d\n", ndime); // all interior elements are printed in a single section; indices start at 0; // node ordering is the same as VTK int nelem = 0; if(ndime == 2){ for(fiter it = firstFace(); it != lastFace(); it++) if(saveAll || (*it)->physicals.size()) nelem += (*it)->getNumMeshElements(); } else{ for(riter it = firstRegion(); it != lastRegion(); it++) if(saveAll || (*it)->physicals.size()) nelem += (*it)->getNumMeshElements(); } int npoin = indexMeshVertices(saveAll); Msg::Info("Writing %d elements and %d vertices", nelem, npoin); // elements fprintf(fp, "NELEM= %d\n", nelem); int num = 0; if(ndime == 2){ for(fiter it = firstFace(); it != lastFace(); it++) if(saveAll || (*it)->physicals.size()) for(unsigned int i = 0; i < (*it)->getNumMeshElements(); i++) (*it)->getMeshElement(i)->writeSU2(fp, num++); } else{ for(riter it = firstRegion(); it != lastRegion(); it++) if(saveAll || (*it)->physicals.size()) for(unsigned int i = 0; i < (*it)->getNumMeshElements(); i++) (*it)->getMeshElement(i)->writeSU2(fp, num++); } // vertices fprintf(fp, "NPOIN= %d\n", npoin); std::vector<GEntity*> entities; getEntities(entities); for(unsigned int i = 0; i < entities.size(); i++) for(unsigned int j = 0; j < entities[i]->mesh_vertices.size(); j++) entities[i]->mesh_vertices[j]->writeSU2(fp, ndime, scalingFactor); // markers for physical groups of dimension (ndime - 1) std::map<int, std::vector<GEntity*> > groups[4]; getPhysicalGroups(groups); int nmark = groups[ndime - 1].size(); if(nmark){ fprintf(fp, "NMARK= %d\n", nmark); for(std::map<int, std::vector<GEntity*> >::iterator it = groups[ndime - 1].begin(); it != groups[ndime - 1].end(); it++){ std::vector<GEntity *> &entities = it->second; int n = 0; for(unsigned int i = 0; i < entities.size(); i++) n += entities[i]->getNumMeshElements(); if(n){ fprintf(fp, "MARKER_TAG= %s\n", physicalName(this, ndime - 1, it->first).c_str()); fprintf(fp, "MARKER_ELEMS= %d\n", n); for(unsigned int i = 0; i < entities.size(); i++) for(unsigned int j = 0; j < entities[i]->getNumMeshElements(); j++) entities[i]->getMeshElement(j)->writeSU2(fp, -1); } } } fclose(fp); return 1; }