QVariant Vertex::itemChange(GraphicsItemChange change, const QVariant &value) { switch (change) { case ItemPositionHasChanged: if (firstEdge()) { firstEdge()->adjust(); } if (secondEdge()){ secondEdge()->adjust(); } break; default: break; }; return QGraphicsItem::itemChange(change, value); }
int GModel::writeGEO(const std::string &name, bool printLabels, bool onlyPhysicals) { FILE *fp = Fopen(name.c_str(), "w"); std::map<double, std::string> meshSizeParameters; int cpt = 0; for(viter it = firstVertex(); it != lastVertex(); it++){ double val = (*it)->prescribedMeshSizeAtVertex(); if(meshSizeParameters.find(val) == meshSizeParameters.end()){ std::ostringstream paramName; paramName << "cl__" << ++cpt; fprintf(fp, "%s = %.16g;\n", paramName.str().c_str(),val); meshSizeParameters.insert(std::make_pair(val, paramName.str())); } } for(viter it = firstVertex(); it != lastVertex(); it++){ double val = (*it)->prescribedMeshSizeAtVertex(); if(!onlyPhysicals || !skipVertex(*it)) (*it)->writeGEO(fp, meshSizeParameters[val]); } for(eiter it = firstEdge(); it != lastEdge(); it++){ if(!onlyPhysicals || !skipEdge(*it)) (*it)->writeGEO(fp); } for(fiter it = firstFace(); it != lastFace(); it++){ if(!onlyPhysicals || !skipFace(*it)) (*it)->writeGEO(fp); } for(riter it = firstRegion(); it != lastRegion(); it++){ if(!onlyPhysicals || !skipRegion(*it)) (*it)->writeGEO(fp); } std::map<int, std::string> labels; #if defined(HAVE_PARSER) // get "old-style" labels from parser for(std::map<std::string, gmsh_yysymbol>::iterator it = gmsh_yysymbols.begin(); it != gmsh_yysymbols.end(); ++it) for(unsigned int i = 0; i < it->second.value.size(); i++) labels[(int)it->second.value[i]] = it->first; #endif std::map<int, std::vector<GEntity*> > groups[4]; getPhysicalGroups(groups); for(int i = 0; i < 4; i++) std::for_each(groups[i].begin(), groups[i].end(), writePhysicalGroupGEO(fp, i, printLabels, labels, physicalNames)); std::for_each(getFields()->begin(), getFields()->end(), writeFieldGEO(fp)); if(getFields()->getBackgroundField() > 0) fprintf(fp, "Background Field = %i;\n", getFields()->getBackgroundField()); if(fp) 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::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::exportDiscreteGEOInternals() { if(_geo_internals) delete _geo_internals; _geo_internals = new GEO_Internals; for(viter it = firstVertex(); it != lastVertex(); it++){ Vertex *v = Create_Vertex((*it)->tag(), (*it)->x(), (*it)->y(), (*it)->z(), (*it)->prescribedMeshSizeAtVertex(), 1.0); Tree_Add(this->getGEOInternals()->Points, &v); } for(eiter it = firstEdge(); it != lastEdge(); it++){ if((*it)->geomType() == GEntity::DiscreteCurve){ Curve *c = Create_Curve((*it)->tag(), MSH_SEGM_DISCRETE, 1, NULL, NULL, -1, -1, 0., 1.); List_T *points = Tree2List(_geo_internals->Points); GVertex *gvb = (*it)->getBeginVertex(); GVertex *gve = (*it)->getEndVertex(); int nb = 2 ; c->Control_Points = List_Create(nb, 1, sizeof(Vertex *)); for(int i = 0; i < List_Nbr(points); i++) { Vertex *v; List_Read(points, i, &v); if (v->Num == gvb->tag()) { List_Add(c->Control_Points, &v); c->beg = v; } if (v->Num == gve->tag()) { List_Add(c->Control_Points, &v); c->end = v; } } End_Curve(c); Tree_Add(this->getGEOInternals()->Curves, &c); CreateReversedCurve(c); List_Delete(points); } } for(fiter it = firstFace(); it != lastFace(); it++){ if((*it)->geomType() == GEntity::DiscreteSurface){ Surface *s = Create_Surface((*it)->tag(), MSH_SURF_DISCRETE); std::list<GEdge*> edges = (*it)->edges(); s->Generatrices = List_Create(edges.size(), 1, sizeof(Curve *)); List_T *curves = Tree2List(_geo_internals->Curves); Curve *c; for(std::list<GEdge*>::iterator ite = edges.begin(); ite != edges.end(); ite++){ for(int i = 0; i < List_Nbr(curves); i++) { List_Read(curves, i, &c); if (c->Num == (*ite)->tag()) { List_Add(s->Generatrices, &c); } } } Tree_Add(this->getGEOInternals()->Surfaces, &s); List_Delete(curves); } } // TODO: create Volumes from discreteRegions Msg::Debug("Geo internal model has:"); Msg::Debug("%d Vertices", Tree_Nbr(_geo_internals->Points)); Msg::Debug("%d Edges", Tree_Nbr(_geo_internals->Curves)); Msg::Debug("%d Faces", Tree_Nbr(_geo_internals->Surfaces)); return 1; }
int GModel::importGEOInternals() { if(Tree_Nbr(_geo_internals->Points)) { List_T *points = Tree2List(_geo_internals->Points); for(int i = 0; i < List_Nbr(points); i++){ Vertex *p; List_Read(points, i, &p); GVertex *v = getVertexByTag(p->Num); if(!v){ v = new gmshVertex(this, p); add(v); } if(!p->Visible) v->setVisibility(0); } List_Delete(points); } if(Tree_Nbr(_geo_internals->Curves)) { List_T *curves = Tree2List(_geo_internals->Curves); for(int i = 0; i < List_Nbr(curves); i++){ Curve *c; List_Read(curves, i, &c); if(c->Num >= 0){ GEdge *e = getEdgeByTag(c->Num); if(!e && c->Typ == MSH_SEGM_COMPOUND){ std::vector<GEdge*> comp; for(unsigned int j = 0; j < c->compound.size(); j++){ GEdge *ge = getEdgeByTag(c->compound[j]); if(ge) comp.push_back(ge); } e = new GEdgeCompound(this, c->Num, comp); e->meshAttributes.method = c->Method; e->meshAttributes.nbPointsTransfinite = c->nbPointsTransfinite; e->meshAttributes.typeTransfinite = c->typeTransfinite; e->meshAttributes.coeffTransfinite = c->coeffTransfinite; e->meshAttributes.extrude = c->Extrude; e->meshAttributes.reverseMesh = c->ReverseMesh; add(e); } else if(!e && c->beg && c->end){ e = new gmshEdge(this, c, getVertexByTag(c->beg->Num), getVertexByTag(c->end->Num)); add(e); } else if(!e){ e = new gmshEdge(this, c, 0, 0); add(e); } if(!c->Visible) e->setVisibility(0); if(c->Color.type) e->setColor(c->Color.mesh); if(c->degenerated) { e->setTooSmall(true); } } } List_Delete(curves); } if(Tree_Nbr(_geo_internals->Surfaces)) { List_T *surfaces = Tree2List(_geo_internals->Surfaces); for(int i = 0; i < List_Nbr(surfaces); i++){ Surface *s; List_Read(surfaces, i, &s); GFace *f = getFaceByTag(s->Num); if(!f && s->Typ == MSH_SURF_COMPOUND){ std::list<GFace*> comp; for(unsigned int j = 0; j < s->compound.size(); j++){ GFace *gf = getFaceByTag(s->compound[j]); if(gf) comp.push_back(gf); } std::list<GEdge*> b[4]; for(int j = 0; j < 4; j++){ for(unsigned int k = 0; k < s->compoundBoundary[j].size(); k++){ GEdge *ge = getEdgeByTag(s->compoundBoundary[j][k]); if(ge) b[j].push_back(ge); } } int param = CTX::instance()->mesh.remeshParam; GFaceCompound::typeOfCompound typ = GFaceCompound::HARMONIC_CIRCLE; if (param == 1) typ = GFaceCompound::CONFORMAL_SPECTRAL; if (param == 2) typ = GFaceCompound::RADIAL_BASIS; if (param == 3) typ = GFaceCompound::HARMONIC_PLANE; if (param == 4) typ = GFaceCompound::CONVEX_CIRCLE; if (param == 5) typ = GFaceCompound::CONVEX_PLANE; if (param == 6) typ = GFaceCompound::HARMONIC_SQUARE; if (param == 7) typ = GFaceCompound::CONFORMAL_FE; int algo = CTX::instance()->mesh.remeshAlgo; f = new GFaceCompound(this, s->Num, comp, b[0], b[1], b[2], b[3], typ, algo); f->meshAttributes.recombine = s->Recombine; f->meshAttributes.recombineAngle = s->RecombineAngle; f->meshAttributes.method = s->Method; f->meshAttributes.extrude = s->Extrude; // transfinite import Added by Trevor Strickler. This helps when experimenting // to create compounds from transfinite surfs. Not having it does not break // anything Gmsh *officially* does right now, but maybe it was left out by mistake??? and could // cause problems later? f->meshAttributes.transfiniteArrangement = s->Recombine_Dir; f->meshAttributes.corners.clear(); for(int i = 0; i < List_Nbr(s->TrsfPoints); i++){ Vertex *corn; List_Read(s->TrsfPoints, i, &corn); GVertex *gv = f->model()->getVertexByTag(corn->Num); if(gv) f->meshAttributes.corners.push_back(gv); else Msg::Error("Unknown vertex %d in transfinite attributes", corn->Num); } add(f); if(s->EmbeddedCurves){ for(int i = 0; i < List_Nbr(s->EmbeddedCurves); i++){ Curve *c; List_Read(s->EmbeddedCurves, i, &c); GEdge *e = getEdgeByTag(abs(c->Num)); if(e) f->addEmbeddedEdge(e); else Msg::Error("Unknown curve %d", c->Num); } } if(s->EmbeddedPoints){ for(int i = 0; i < List_Nbr(s->EmbeddedPoints); i++){ Vertex *v; List_Read(s->EmbeddedPoints, i, &v); GVertex *gv = getVertexByTag(v->Num); if(gv) f->addEmbeddedVertex(gv); else Msg::Error("Unknown point %d", v->Num); } } } else if(!f){ f = new gmshFace(this, s); add(f); } else f->resetMeshAttributes(); if(!s->Visible) f->setVisibility(0); if(s->Color.type) f->setColor(s->Color.mesh); } List_Delete(surfaces); } if(Tree_Nbr(_geo_internals->Volumes)) { List_T *volumes = Tree2List(_geo_internals->Volumes); for(int i = 0; i < List_Nbr(volumes); i++){ Volume *v; List_Read(volumes, i, &v); GRegion *r = getRegionByTag(v->Num); if(!r && v->Typ == MSH_VOLUME_COMPOUND){ std::vector<GRegion*> comp; for(unsigned int j = 0; j < v->compound.size(); j++){ GRegion *gr = getRegionByTag(v->compound[j]); if(gr) comp.push_back(gr); } r = new GRegionCompound(this, v->Num, comp); if(v->EmbeddedSurfaces){ for(int i = 0; i < List_Nbr(v->EmbeddedSurfaces); i++){ Surface *s; List_Read(v->EmbeddedSurfaces, i, &s); GFace *gf = getFaceByTag(abs(s->Num)); if(gf) r->addEmbeddedFace(gf); else Msg::Error("Unknown surface %d", s->Num); } } add(r); } else if(!r){ r = new gmshRegion(this, v); add(r); } else r->resetMeshAttributes(); if(!v->Visible) r->setVisibility(0); if(v->Color.type) r->setColor(v->Color.mesh); } List_Delete(volumes); } for(int i = 0; i < List_Nbr(_geo_internals->PhysicalGroups); i++){ PhysicalGroup *p; List_Read(_geo_internals->PhysicalGroups, i, &p); for(int j = 0; j < List_Nbr(p->Entities); j++){ int num; List_Read(p->Entities, j, &num); GEntity *ge = 0; int tag = CTX::instance()->geom.orientedPhysicals ? abs(num) : num; switch(p->Typ){ case MSH_PHYSICAL_POINT: ge = getVertexByTag(tag); break; case MSH_PHYSICAL_LINE: ge = getEdgeByTag(tag); break; case MSH_PHYSICAL_SURFACE: ge = getFaceByTag(tag); break; case MSH_PHYSICAL_VOLUME: ge = getRegionByTag(tag); break; } int pnum = CTX::instance()->geom.orientedPhysicals ? (sign(num) * p->Num) : p->Num; if(ge && std::find(ge->physicals.begin(), ge->physicals.end(), pnum) == ge->physicals.end()) ge->physicals.push_back(pnum); } } // create periodic mesh relationships for (std::map<int,int>::iterator it = _geo_internals->periodicEdges.begin(); it != _geo_internals->periodicEdges.end(); ++it){ GEdge *ge = getEdgeByTag(abs(it->first)); if (ge){ int MASTER = it->second * (it->first > 0 ? 1 : -1); ge->setMeshMaster(MASTER); } } for (std::map<int,int>::iterator it = _geo_internals->periodicFaces.begin(); it != _geo_internals->periodicFaces.end(); ++it){ GFace *gf = getFaceByTag(abs(it->first)); if (gf)gf->setMeshMaster(it->second * (it->first > 0 ? 1 : -1)); } for (eiter it = firstEdge() ; it != lastEdge() ; ++it){ int meshMaster = (*it)->meshMaster(); if (meshMaster != (*it)->tag()){ GEdge *ge_master = getEdgeByTag(abs(meshMaster)); if(ge_master)(*it)->getBeginVertex()->setMeshMaster ( (meshMaster > 0) ? ge_master->getBeginVertex()->tag() : ge_master->getEndVertex()->tag()); if(ge_master)(*it)->getEndVertex()->setMeshMaster ( (meshMaster < 0) ? ge_master->getBeginVertex()->tag() : ge_master->getEndVertex()->tag()); } } Msg::Debug("Gmsh model (GModel) imported:"); Msg::Debug("%d Vertices", vertices.size()); Msg::Debug("%d Edges", edges.size()); Msg::Debug("%d Faces", faces.size()); Msg::Debug("%d Regions", regions.size()); 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; }