// sets the entity m from which the mesh will be copied void GEntity::setMeshMaster(int m_signed) { if(m_signed == tag()){ _meshMaster = m_signed; return; } GEntity *gMaster = 0; int m = abs(m_signed); switch(dim()){ case 0 : gMaster = model()->getVertexByTag(m); break; case 1 : gMaster = model()->getEdgeByTag(m); break; case 2 : gMaster = model()->getFaceByTag(m); break; case 3 : gMaster = model()->getRegionByTag(m); break; } if (!gMaster){ Msg::Error("Model entity %d of dimension %d cannot be the mesh master of entity %d", m, dim(), tag()); return; } int masterOfMaster = gMaster->meshMaster(); if (masterOfMaster == gMaster->tag()){ _meshMaster = m_signed; } else { setMeshMaster ( masterOfMaster * ((m_signed > 0) ? 1 : -1)); } }
int main(int argc, char **argv) { GmshInitialize(argc, argv); GmshSetOption("Mesh", "Algorithm", 5.); GmshSetOption("General", "Terminal", 1.); GModel *m = new GModel(); m->readMSH("bunny.msh"); m->fillVertexArrays(); std::vector<GEntity*> entities; m->getEntities(entities); for(unsigned int i = 0; i < entities.size(); i++){ GEntity *ge = entities[i]; printf("coucou entite %d (dimension %d)\n", ge->tag(), ge->dim()); if(ge->va_triangles) printf(" j'ai un va de triangles: %d vertex\n", ge->va_triangles->getNumVertices()); if(ge->va_lines) printf(" j'ai un va de lignes: %d vertex\n", ge->va_lines->getNumVertices()); } delete m; GmshFinalize(); }
static void getBoundaryFromMesh(GModel *m, int visible) { int dim = m->getDim(); std::vector<GEntity*> entities; m->getEntities(entities); std::set<MFace, Less_Face> bndFaces; std::set<MEdge, Less_Edge> bndEdges; for(unsigned int i = 0; i < entities.size(); i++){ GEntity *ge = entities[i]; if(ge->dim() != dim) continue; if(visible && !ge->getVisibility()) continue; for(unsigned int j = 0; j < ge->getNumMeshElements(); j++){ MElement *e = ge->getMeshElement(j); if(dim == 2){ for(int i = 0; i < e->getNumEdges(); i++){ MEdge f = e->getEdge(i); if(bndEdges.find(f) == bndEdges.end()) bndEdges.insert(f); else bndEdges.erase(f); } } else if(dim == 3){ for(int i = 0; i < e->getNumFaces(); i++){ MFace f = e->getFace(i); if(bndFaces.find(f) == bndFaces.end()) bndFaces.insert(f); else bndFaces.erase(f); } } } } if(dim == 2){ discreteEdge *e = new discreteEdge(m, m->getMaxElementaryNumber(1) + 1, 0, 0); m->add(e); for(std::set<MEdge, Less_Edge>::iterator it = bndEdges.begin(); it != bndEdges.end(); it++){ e->lines.push_back(new MLine(it->getVertex(0), it->getVertex(1))); } } else if(dim == 3){ discreteFace *f = new discreteFace(m, m->getMaxElementaryNumber(2) + 1); m->add(f); for(std::set<MFace, Less_Face>::iterator it = bndFaces.begin(); it != bndFaces.end(); it++){ if(it->getNumVertices() == 3) f->triangles.push_back(new MTriangle(it->getVertex(0), it->getVertex(1), it->getVertex(2))); else if(it->getNumVertices() == 4) f->quadrangles.push_back(new MQuadrangle(it->getVertex(0), it->getVertex(1), it->getVertex(2), it->getVertex(3))); } } }
void Mesh::calcScaledNormalEl2D(const std::map<MElement*,GEntity*> &element2entity, int iEl) { const JacobianBasis *jac = _el[iEl]->getJacobianFuncSpace(); fullMatrix<double> primNodesXYZ(jac->getNumPrimMapNodes(),3); SVector3 geoNorm(0.,0.,0.); std::map<MElement*,GEntity*>::const_iterator itEl2ent = element2entity.find(_el[iEl]); GEntity *ge = (itEl2ent == element2entity.end()) ? 0 : itEl2ent->second; const bool hasGeoNorm = ge && (ge->dim() == 2) && ge->haveParametrization(); for (int i=0; i<jac->getNumPrimMapNodes(); i++) { const int &iV = _el2V[iEl][i]; primNodesXYZ(i,0) = _xyz[iV].x(); primNodesXYZ(i,1) = _xyz[iV].y(); primNodesXYZ(i,2) = _xyz[iV].z(); if (hasGeoNorm && (_vert[iV]->onWhat() == ge)) { double u, v; _vert[iV]->getParameter(0,u); _vert[iV]->getParameter(1,v); geoNorm += ((GFace*)ge)->normal(SPoint2(u,v)); } } if (hasGeoNorm && (geoNorm.normSq() == 0.)) { SPoint2 param = ((GFace*)ge)->parFromPoint(_el[iEl]->barycenter(true),false); geoNorm = ((GFace*)ge)->normal(param); } fullMatrix<double> &elNorm = _scaledNormEl[iEl]; elNorm.resize(1,3); const double norm = jac->getPrimNormal2D(primNodesXYZ,elNorm); double factor = 1./norm; if (hasGeoNorm) { const double scal = geoNorm(0)*elNorm(0,0)+geoNorm(1)*elNorm(0,1)+geoNorm(2)*elNorm(0,2); if (scal < 0.) factor = -factor; } elNorm.scale(factor); // Re-scaling normal here is faster than an extra scaling operation on the Jacobian }
// gets the entity from which the mesh will be copied int GEntity::meshMaster() const { if (_meshMaster == tag()) return tag(); GEntity *gMaster = 0; switch(dim()){ case 0 : gMaster = model()->getVertexByTag(abs(_meshMaster)); break; case 1 : gMaster = model()->getEdgeByTag(abs(_meshMaster)); break; case 2 : gMaster = model()->getFaceByTag(abs(_meshMaster)); break; case 3 : gMaster = model()->getRegionByTag(abs(_meshMaster)); break; } if (!gMaster){ Msg::Error("Could not find mesh master entity %d",_meshMaster); return tag(); } int masterOfMaster = gMaster->meshMaster(); if (masterOfMaster == gMaster->tag()){ return _meshMaster ; } else { return gMaster->meshMaster() * ((_meshMaster > 0) ? 1 : -1); } }
void updateBoVec<3, MFace>( const int normalSource, const MVertex *const vertex, const int zoneIndex, const int vertIndex, const CCon::FaceVector<MZoneBoundary<3>::GlobalVertexData<MFace>::FaceDataB> &faces, ZoneBoVec &zoneBoVec, BCPatchIndex &patch, bool &warnNormFromElem) { GEntity *ent; if(normalSource == NormalSourceElement) goto getNormalFromElements; ent = vertex->onWhat(); if(ent == 0) { goto getNormalFromElements; // No entity: try to find a normal from the faces } else { switch(ent->dim()) { case 0: case 1: /*--------------------------------------------------------------------* * In this case, there are possibly multiple GFaces from this zone * connected to the vertex. One patch for each GFace will be written. *--------------------------------------------------------------------*/ { //--Get a list of face entities connected to 'ent' std::list<GFace *> gFaceList; switch(ent->dim()) { case 0: { std::vector<GEdge *> gEdgeList = ent->edges(); std::list<GFace *> gFaceList; for(std::vector<GEdge *>::const_iterator gEIt = gEdgeList.begin(); gEIt != gEdgeList.end(); ++gEIt) { std::vector<GFace *> alist = (*gEIt)->faces(); gFaceList.insert(gFaceList.end(), alist.begin(), alist.end()); } // Remove duplicates gFaceList.sort(); gFaceList.unique(); } break; case 1: { std::vector<GFace *> fac = ent->faces(); gFaceList.insert(gFaceList.end(), fac.begin(), fac.end()); } break; } //--Get a list of face entities connected to the 'vertex' that are also // in the //--zone std::list<const GFace *> useGFace; std::vector<GEdge *> gEdgeList; const int nFace = faces.size(); for(int iFace = 0; iFace != nFace; ++iFace) { if(zoneIndex == faces[iFace].zoneIndex) { bool matchedFace = false; MFace mFace = faces[iFace].parentElement->getFace(faces[iFace].parentFace); const int nVOnF = mFace.getNumVertices(); int vertexOnF = 0; // The index of 'vertex' in the face for(int iVOnF = 0; iVOnF != nVOnF; ++iVOnF) { const MVertex *const vertex2 = mFace.getVertex(iVOnF); if(vertex == vertex2) vertexOnF = iVOnF; else { const GEntity *const ent2 = vertex2->onWhat(); if(ent2->dim() == 2) { matchedFace = true; useGFace.push_back(static_cast<const GFace *>(ent2)); break; } } } // Triangle MElements are a total P.I.T.A.: // - If the original 'ent' is a vertex, one MVertex can be on the // GVertex, and the other two on GEdges, and then the MElement is // still on the GFace. // - If the original 'ent' is an edge, one MVertex can be on the // original GEdge, another on a GVertex, and the final on another // GEdge, and then the MElement is still on the GFace. There is // also the unlikely case where the two other MVertex are both on // edges ... and the MElement is still on the GFace. if(!matchedFace && (3 == nVOnF)) { const MVertex *vertex2 = 0; const MVertex *vertex3 = 0; switch(vertexOnF) { case 0: vertex2 = mFace.getVertex(1); vertex3 = mFace.getVertex(2); break; case 1: vertex2 = mFace.getVertex(0); vertex3 = mFace.getVertex(2); break; case 2: vertex2 = mFace.getVertex(0); vertex3 = mFace.getVertex(1); break; } if(vertex2 && vertex3) { const GEntity *const ent2 = vertex2->onWhat(); const GEntity *const ent3 = vertex3->onWhat(); if(ent2 && ent3) { if(ent2->dim() == 1 && ent3->dim() == 1) { // Which GFace is bounded by edges ent2 and ent3? for(std::list<GFace *>::const_iterator gFIt = gFaceList.begin(); gFIt != gFaceList.end(); ++gFIt) { gEdgeList = (*gFIt)->edges(); if((std::find(gEdgeList.begin(), gEdgeList.end(), ent2) != gEdgeList.end()) && (std::find(gEdgeList.begin(), gEdgeList.end(), ent3) != gEdgeList.end())) { // Edges ent2 and ent3 bound this face useGFace.push_back(*gFIt); break; } } } else if(ent->dim() == 1 && (ent2->dim() + ent3->dim() == 1)) { const GEntity *entCmp; if(ent2->dim() == 1) entCmp = ent2; else entCmp = ent3; // Which GFace is bounded by entCmp for(std::list<GFace *>::const_iterator gFIt = gFaceList.begin(); gFIt != gFaceList.end(); ++gFIt) { gEdgeList = (*gFIt)->edges(); if(std::find(gEdgeList.begin(), gEdgeList.end(), entCmp) != gEdgeList.end()) { // Edge entCmp and the original edge bound this face useGFace.push_back(*gFIt); break; } } } } } } // Stupid triangles } // End if face in zone } // End loop over faces // Duplicates are a possibility, remove useGFace.sort(); useGFace.unique(); //--'useGFace' now contains the face entities that connect to vertex. A // BC //--patch will be written for each of them. for(std::list<const GFace *>::const_iterator gFIt = useGFace.begin(); gFIt != useGFace.end(); ++gFIt) { SPoint2 par; if(!reparamMeshVertexOnFace(const_cast<MVertex *>(vertex), *gFIt, par)) goto getNormalFromElements; // :P After all that! SVector3 boNormal = (*gFIt)->normal(par); SPoint3 interior(0., 0., 0.); int cFace = 0; const int nFace = faces.size(); for(int iFace = 0; iFace != nFace; ++iFace) { if(faces[iFace].zoneIndex == zoneIndex) { ++cFace; interior += faces[iFace].parentElement->barycenter(); } } interior /= cFace; if(dot(boNormal, SVector3(vertex->point(), interior)) < 0.) boNormal.negate(); zoneBoVec.push_back( VertexBoundary(zoneIndex, (*gFIt)->tag(), boNormal, const_cast<MVertex *>(vertex), vertIndex)); patch.add((*gFIt)->tag()); } } break; case 2: /*--------------------------------------------------------------------* * The vertex exists on a face and belongs to only 1 BC patch. *--------------------------------------------------------------------*/ { const GFace *const gFace = static_cast<const GFace *>(ent); SPoint2 par; if(!reparamMeshVertexOnFace(const_cast<MVertex *>(vertex), gFace, par)) goto getNormalFromElements; SVector3 boNormal = static_cast<const GFace *>(ent)->normal(par); SPoint3 interior(0., 0., 0.); int cFace = 0; const int nFace = faces.size(); for(int iFace = 0; iFace != nFace; ++iFace) { if(faces[iFace].zoneIndex == zoneIndex) { ++cFace; interior += faces[iFace].parentElement->barycenter(); } } interior /= cFace; if(dot(boNormal, SVector3(vertex->point(), interior)) < 0.) boNormal.negate(); zoneBoVec.push_back(VertexBoundary(zoneIndex, gFace->tag(), boNormal, const_cast<MVertex *>(vertex), vertIndex)); patch.add(gFace->tag()); } break; default: goto getNormalFromElements; } } return; getNormalFromElements:; /*--------------------------------------------------------------------* * Geometry information cannot be used - generate normals from the * elements *--------------------------------------------------------------------*/ { if(warnNormFromElem && normalSource == 1) { Msg::Warning("Some or all boundary normals were determined from mesh " "elements instead of from the geometry"); warnNormFromElem = false; } // Sum the normals from each element connected to the vertex and in the // zone. Each normal has to be converted independently into an inwards- // pointing normal. //**Weight each normal by the area of the boundary element? SVector3 boNormal(0.); const int nFace = faces.size(); for(int iFace = 0; iFace != nFace; ++iFace) { if(faces[iFace].zoneIndex == zoneIndex) { // Normal to the boundary (unknown direction) SVector3 bnt = faces[iFace].parentElement->getFace(faces[iFace].parentFace).normal(); // Inwards normal const SVector3 inwards(vertex->point(), faces[iFace].parentElement->barycenter()); if(dot(bnt, inwards) < 0.) bnt.negate(); boNormal += bnt; } } boNormal.normalize(); zoneBoVec.push_back(VertexBoundary( zoneIndex, 0, boNormal, const_cast<MVertex *>(vertex), vertIndex)); patch.add(0); } }
void updateBoVec<2, MEdge>( const int normalSource, const MVertex *const vertex, const int zoneIndex, const int vertIndex, const CCon::FaceVector<MZoneBoundary<2>::GlobalVertexData<MEdge>::FaceDataB> &faces, ZoneBoVec &zoneBoVec, BCPatchIndex &patch, bool &warnNormFromElem) { GEntity *ent; if(normalSource == NormalSourceElement) goto getNormalFromElements; ent = vertex->onWhat(); if(ent == 0) { goto getNormalFromElements; // No entity: try to find a normal from the faces } else { switch(ent->dim()) { case 0: /*--------------------------------------------------------------------* * In this case, there are possibly two GEdges from this zone * connected to the vertex. If the angle between the two edges is * significant, the BC patch will be split and this vertex will be * written in both patches with different normals. If the angle is * small, or only one GEdge belongs to this zone, then the vertex will * only be written to one patch. *--------------------------------------------------------------------*/ { // Find edge entities that are connected to elements in the zone std::vector<std::pair<GEdge *, int> > useGEdge; const int nFace = faces.size(); for(int iFace = 0; iFace != nFace; ++iFace) { if(zoneIndex == faces[iFace].zoneIndex) { MEdge mEdge = faces[iFace].parentElement->getEdge(faces[iFace].parentFace); // Get the other vertex on the mesh edge. MVertex *vertex2 = mEdge.getMinVertex(); if(vertex2 == vertex) vertex2 = mEdge.getMaxVertex(); // Check if the entity associated with vertex2 is a line and // is also connected to vertex. If so, add it to the container of // edge entities that will be used to determine the normal GEntity *const ent2 = vertex2->onWhat(); if(ent2->dim() == 1) { useGEdge.push_back( std::pair<GEdge *, int>(static_cast<GEdge *>(ent2), iFace)); } } } //--'useGEdge' now contains the edge entities that will be used to // determine //--the normals switch(useGEdge.size()) { case 0: // goto getNormalFromElements; // We probably don't want BC data if none of the faces attatched to // this vertex and in this zone are on the boundary. break; case 1: { const GEdge *const gEdge = static_cast<const GEdge *>(useGEdge[0].first); SVector3 boNormal; if(edge_normal(vertex, zoneIndex, gEdge, faces, boNormal)) goto getNormalFromElements; zoneBoVec.push_back(VertexBoundary(zoneIndex, gEdge->tag(), boNormal, const_cast<MVertex *>(vertex), vertIndex)); patch.add(gEdge->tag()); } break; case 2: { // Get the first normal const GEdge *const gEdge1 = static_cast<const GEdge *>(useGEdge[0].first); SVector3 boNormal1; if(edge_normal(vertex, zoneIndex, gEdge1, faces, boNormal1, useGEdge[0].second)) goto getNormalFromElements; // Get the second normal const GEdge *const gEdge2 = static_cast<const GEdge *>(useGEdge[1].first); SVector3 boNormal2; if(edge_normal(vertex, zoneIndex, gEdge2, faces, boNormal2, useGEdge[1].second)) goto getNormalFromElements; if(dot(boNormal1, boNormal2) < 0.98) { //--Write 2 separate patches zoneBoVec.push_back( VertexBoundary(zoneIndex, gEdge1->tag(), boNormal1, const_cast<MVertex *>(vertex), vertIndex)); patch.add(gEdge1->tag()); zoneBoVec.push_back( VertexBoundary(zoneIndex, gEdge2->tag(), boNormal2, const_cast<MVertex *>(vertex), vertIndex)); patch.add(gEdge2->tag()); } else { //--Write one patch boNormal1 += boNormal2; boNormal1 *= 0.5; zoneBoVec.push_back( VertexBoundary(zoneIndex, gEdge1->tag(), boNormal1, const_cast<MVertex *>(vertex), vertIndex)); patch.addPair(gEdge1->tag(), gEdge2->tag()); } } break; default: Msg::Error("Internal error based on 2-D boundary assumptions (file " "\'MZoneBoundary.cpp'). Boundary vertices may be " "incorrect"); break; } } break; case 1: /*--------------------------------------------------------------------* * The vertex exists on an edge and belongs to only 1 BC patch. *--------------------------------------------------------------------*/ { SVector3 boNormal; if(edge_normal(vertex, zoneIndex, static_cast<const GEdge *>(ent), faces, boNormal)) goto getNormalFromElements; zoneBoVec.push_back(VertexBoundary(zoneIndex, ent->tag(), boNormal, const_cast<MVertex *>(vertex), vertIndex)); patch.add(ent->tag()); } break; default: goto getNormalFromElements; } } return; getNormalFromElements:; /*--------------------------------------------------------------------* * Geometry information cannot be used - generate normals from the * elements *--------------------------------------------------------------------*/ { if(warnNormFromElem && normalSource == 1) { Msg::Warning("Some or all boundary normals were determined from mesh " "elements instead of from the geometry"); warnNormFromElem = false; } // The mesh plane normal is computed from all elements attached to the // vertex SVector3 meshPlaneNormal(0.); // This normal is perpendicular to the // plane of the mesh const int nFace = faces.size(); for(int iFace = 0; iFace != nFace; ++iFace) { if(faces[iFace].zoneIndex == zoneIndex) { // Make sure all the planes go in the same direction //**Required? SVector3 mpnt = faces[iFace].parentElement->getFace(0).normal(); if(dot(mpnt, meshPlaneNormal) < 0.) mpnt.negate(); meshPlaneNormal += mpnt; } } // Sum the normals from each element. The tangent is computed from all // faces in the zone attached to the vertex and is weighted by the length of // the edge. Each tangent has to be converted independently into an // inwards-pointing normal. SVector3 boNormal(0.); for(int iFace = 0; iFace != nFace; ++iFace) { if(faces[iFace].zoneIndex == zoneIndex) { const SVector3 tangent = faces[iFace] .parentElement->getEdge(faces[iFace].parentFace) .tangent(); // Normal to the boundary (unknown direction) SVector3 bnt = crossprod(tangent, meshPlaneNormal); // Inwards normal const SVector3 inwards(vertex->point(), faces[iFace].parentElement->barycenter()); if(dot(bnt, inwards) < 0.) bnt.negate(); boNormal += bnt; } } boNormal.normalize(); zoneBoVec.push_back(VertexBoundary( zoneIndex, 0, boNormal, const_cast<MVertex *>(vertex), vertIndex)); patch.add(0); } }
PView *GMSH_DistancePlugin::execute(PView *v) { int id_pt = (int) DistanceOptions_Number[0].def; int id_line = (int) DistanceOptions_Number[1].def; int id_face = (int) DistanceOptions_Number[2].def; double type = (double) DistanceOptions_Number[3].def; int ortho = (int) DistanceOptions_Number[6].def; PView *view = new PView(); _data = getDataList(view); #if defined(HAVE_SOLVER) #if defined(HAVE_TAUCS) linearSystemCSRTaucs<double> *lsys = new linearSystemCSRTaucs<double>; #else linearSystemCSRGmm<double> *lsys = new linearSystemCSRGmm<double>; lsys->setNoisy(1); lsys->setGmres(1); lsys->setPrec(5.e-8); #endif dofManager<double> * dofView = new dofManager<double>(lsys); #endif std::vector<GEntity*> _entities; GModel::current()->getEntities(_entities); if (!_entities.size() || !_entities[_entities.size()-1]->getMeshElement(0)) { Msg::Error("This plugin needs a mesh !"); return view; } GEntity* ge = _entities[_entities.size()-1]; int integrationPointTetra[2] = {0,0}; int numnodes = 0; for (unsigned int i = 0; i < _entities.size()-1; i++) numnodes += _entities[i]->mesh_vertices.size(); int totNodes = numnodes + _entities[_entities.size()-1]->mesh_vertices.size(); int order = ge->getMeshElement(0)->getPolynomialOrder(); int totNumNodes = totNodes + ge->getNumMeshElements()*integrationPointTetra[order-1]; std::vector<SPoint3> pts; std::vector<double> distances; std::vector<MVertex* > pt2Vertex; pts.clear(); distances.clear(); pt2Vertex.clear(); pts.reserve(totNumNodes); distances.reserve(totNumNodes); pt2Vertex.reserve(totNumNodes); std::map<MVertex*,double> _distanceE_map; std::map<MVertex*,int> _isInYarn_map; std::vector<int> index; std::vector<double> distancesE; std::vector<double> distances2; std::vector<double> distancesE2; std::vector<int> isInYarn; std::vector<int> isInYarn2; std::vector<SPoint3> closePts; std::vector<SPoint3> closePts2; for (int i=0; i<totNumNodes; i++) { distances.push_back(1.e22); } int k = 0; for (unsigned int i=0; i<_entities.size(); i++){ GEntity* ge = _entities[i]; _maxDim = std::max(_maxDim, ge->dim()); for (unsigned int j=0; j<ge->mesh_vertices.size(); j++) { MVertex *v = ge->mesh_vertices[j]; pts.push_back(SPoint3(v->x(), v->y(), v->z())); _distance_map.insert(std::make_pair(v, 0.0)); /* TO DO (by AM) SPoint3 p_empty(); _closePts_map.insert(std::make_pair(v, p_empty)); */ pt2Vertex[k] = v; k++; } } // Compute geometrical distance to mesh boundaries //------------------------------------------------------ if (type < 0.0 ) { bool existEntity = false; for (unsigned int i=0; i<_entities.size(); i++) { GEntity* g2 = _entities[i]; int gDim = g2->dim(); std::vector<int> phys = g2->getPhysicalEntities(); bool computeForEntity = false; for(unsigned int k = 0; k<phys.size(); k++) { int tagp = phys[k]; if (id_pt == 0 && id_line == 0 && id_face == 0 && gDim == _maxDim - 1) computeForEntity = true; else if ((tagp == id_pt && gDim == 0) || (tagp == id_line && gDim == 1) || (tagp == id_face && gDim == 2)) computeForEntity = true; } if (computeForEntity) { existEntity = true; for (unsigned int k = 0; k < g2->getNumMeshElements(); k++) { std::vector<double> iDistances; std::vector<SPoint3> iClosePts; std::vector<double> iDistancesE; std::vector<int> iIsInYarn; MElement *e = g2->getMeshElement(k); MVertex *v1 = e->getVertex(0); MVertex *v2 = e->getVertex(1); SPoint3 p1(v1->x(), v1->y(), v1->z()); SPoint3 p2(v2->x(), v2->y(), v2->z()); if ((e->getNumVertices() == 2 && order == 1) || (e->getNumVertices() == 3 && order == 2)) { signedDistancesPointsLine(iDistances, iClosePts, pts, p1, p2); } else if ((e->getNumVertices() == 3 && order == 1) || (e->getNumVertices() == 6 && order == 2)) { MVertex *v3 = e->getVertex(2); SPoint3 p3 (v3->x(),v3->y(),v3->z()); signedDistancesPointsTriangle(iDistances, iClosePts, pts, p1, p2, p3); } for (unsigned int kk=0; kk<pts.size(); kk++) { if (std::abs(iDistances[kk]) < distances[kk]) { distances[kk] = std::abs(iDistances[kk]); MVertex *v = pt2Vertex[kk]; _distance_map[v] = distances[kk]; /* TO DO (by AM) _closePts_map[v] = iClosePts[kk]; */ } } } } } if (!existEntity){ if (id_pt != 0) Msg::Error("The Physical Point does not exist !"); if (id_line != 0) Msg::Error("The Physical Line does not exist !"); if (id_face != 0) Msg::Error("The Physical Surface does not exist !"); return view; } printView(_entities, _distance_map); /* TO DO (by AM) printView(_entities, _closePts_map); */ } // Compute PDE for distance function //----------------------------------- else if (type > 0.0) { #if defined(HAVE_SOLVER) bool existEntity = false; SBoundingBox3d bbox; for(unsigned int i = 0; i < _entities.size(); i++){ GEntity* ge = _entities[i]; int gDim = ge->dim(); bool fixForEntity = false; std::vector<int> phys = ge->getPhysicalEntities(); for(unsigned int k = 0; k < phys.size(); k++) { int tagp = phys[k]; if (id_pt == 0 && id_line == 0 && id_face == 0 && gDim == _maxDim - 1) fixForEntity = true; else if ((tagp == id_pt && gDim == 0) || (tagp == id_line && gDim == 1) || (tagp == id_face && gDim == 2) ) fixForEntity = true; } if (fixForEntity) { existEntity = true; for (unsigned int i = 0; i < ge->getNumMeshElements(); ++i) { MElement *t = ge->getMeshElement(i); for (int k=0; k<t->getNumVertices(); k++) { MVertex *v = t->getVertex(k); dofView->fixVertex(v, 0, 1, 0.); bbox += SPoint3(v->x(), v->y(), v->z()); } } } } if (!existEntity){ if (id_pt != 0) Msg::Error("The Physical Point does not exist !"); if (id_line != 0) Msg::Error("The Physical Line does not exist !"); if (id_face != 0) Msg::Error("The Physical Surface does not exist !"); return view; } std::vector<MElement *> allElems; for(unsigned int ii = 0; ii < _entities.size(); ii++){ if(_entities[ii]->dim() == _maxDim) { GEntity *ge = _entities[ii]; for(unsigned int i = 0; i < ge->getNumMeshElements(); ++i) { MElement *t = ge->getMeshElement(i); allElems.push_back(t); for (int k = 0; k < t->getNumVertices(); k++) dofView->numberVertex(t->getVertex(k), 0, 1); } } } double L = norm(SVector3(bbox.max(), bbox.min())); double mu = type*L; simpleFunction<double> DIFF(mu*mu), ONE(1.0); distanceTerm distance(GModel::current(), 1, &DIFF, &ONE); for (std::vector<MElement* >::iterator it = allElems.begin(); it != allElems.end(); it++){ SElement se((*it)); distance.addToMatrix(*dofView, &se); } groupOfElements gr(allElems); distance.addToRightHandSide(*dofView, gr); Msg::Info("Distance Computation: Assembly done"); lsys->systemSolve(); Msg::Info("Distance Computation: System solved"); for (std::map<MVertex*,double >::iterator itv = _distance_map.begin(); itv != _distance_map.end() ; ++itv) { MVertex *v = itv->first; double value; dofView->getDofValue(v, 0, 1, value); value = std::min(0.9999, value); double dist = -mu * log(1. - value); itv->second = dist; } printView(_entities, _distance_map); #endif } _data->setName("distance"); _data->Time.push_back(0); _data->setFileName(_fileName.c_str()); _data->finalize(); // compute also orthogonal vector to distance field // A Uortho = -C DIST //------------------------------------------------ if (ortho > 0) { #if defined(HAVE_SOLVER) #ifdef HAVE_TAUCS linearSystemCSRTaucs<double> *lsys2 = new linearSystemCSRTaucs<double>; #else linearSystemCSRGmm<double> *lsys2 = new linearSystemCSRGmm<double>; lsys->setNoisy(1); lsys->setGmres(1); lsys->setPrec(5.e-8); #endif dofManager<double> myAssembler(lsys2); simpleFunction<double> ONE(1.0); double dMax = 1.0; //EMI TO CHANGE std::vector<MElement *> allElems; for(unsigned int ii = 0; ii < _entities.size(); ii++){ if (_entities[ii]->dim() == _maxDim) { GEntity *ge = _entities[ii]; for (unsigned int i=0; i<ge->getNumMeshElements(); ++i) { MElement *t = ge->getMeshElement(i); double vMean = 0.0; for (int k = 0; k < t->getNumVertices(); k++) { std::map<MVertex*, double>::iterator it = _distance_map.find(t->getVertex(k)); vMean += it->second; } vMean /= t->getNumVertices(); if (vMean < dMax) allElems.push_back(ge->getMeshElement(i)); } } } int mid = (int)floor(allElems.size() / 2.); MElement *e = allElems[mid]; MVertex *vFIX = e->getVertex(0); myAssembler.fixVertex(vFIX, 0, 1, 0.0); for (std::vector<MElement* >::iterator it = allElems.begin(); it != allElems.end(); it++){ MElement *t = *it; for(int k = 0; k < t->getNumVertices(); k++) myAssembler.numberVertex(t->getVertex(k), 0, 1); } orthogonalTerm *ortho; ortho = new orthogonalTerm(GModel::current(), 1, &ONE, &_distance_map); // if (type < 0) // ortho = new orthogonalTerm(GModel::current(), 1, &ONE, view); // else // ortho = new orthogonalTerm(GModel::current(), 1, &ONE, dofView); for (std::vector<MElement* >::iterator it = allElems.begin(); it != allElems.end(); it++){ SElement se((*it)); ortho->addToMatrix(myAssembler, &se); } groupOfElements gr(allElems); ortho->addToRightHandSide(myAssembler, gr); Msg::Info("Orthogonal Computation: Assembly done"); lsys2->systemSolve(); Msg::Info("Orthogonal Computation: System solved"); PView *view2 = new PView(); PViewDataList *data2 = getDataList(view2); data2->setName("ortogonal field"); Msg::Info("Writing orthogonal.pos"); FILE * f5 = Fopen("orthogonal.pos","w"); fprintf(f5,"View \"orthogonal\"{\n"); for (std::vector<MElement* >::iterator it = allElems.begin(); it != allElems.end(); it++){ MElement *e = *it; int numNodes = e->getNumVertices(); if (e->getType() == TYPE_POLYG) numNodes = e->getNumChildren() * e->getChild(0)->getNumVertices(); std::vector<double> x(numNodes), y(numNodes), z(numNodes); std::vector<double> *out2 = data2->incrementList(1, e->getType(), numNodes); std::vector<MVertex*> nods; std::vector<double> orth; if(!e->getNumChildren()) for(int i=0; i<numNodes; i++) nods.push_back(e->getVertex(i)); else for(int i = 0; i < e->getNumChildren(); i++) for(int j = 0; j < e->getChild(i)->getNumVertices(); j++) nods.push_back(e->getChild(i)->getVertex(j)); for(int nod = 0; nod < numNodes; nod++) out2->push_back((nods[nod])->x()); for(int nod = 0; nod < numNodes; nod++) out2->push_back((nods[nod])->y()); for(int nod = 0; nod < numNodes; nod++) out2->push_back((nods[nod])->z()); if (_maxDim == 2) switch (numNodes) { case 2: fprintf(f5,"SL("); break; case 3: fprintf(f5,"ST("); break; case 4: fprintf(f5,"SQ("); break; default: Msg::Fatal("Error in Plugin 'Distance' (numNodes=%g).",numNodes); break; } else if (_maxDim == 3) switch (numNodes) { case 4: fprintf(f5,"SS("); break; case 8: fprintf(f5,"SH("); break; case 6: fprintf(f5,"SI("); break; case 5: fprintf(f5,"SY("); break; default: Msg::Fatal("Error in Plugin 'Distance' (numNodes=%g).",numNodes); break; } for (int j=0; j<numNodes; j++) { MVertex *v = nods[j]; if (j) fprintf(f5, ",%g,%g,%g", v->x(), v->y(), v->z()); else fprintf(f5, "%g,%g,%g", v->x(), v->y(), v->z()); double value; myAssembler.getDofValue(v, 0, 1, value); orth.push_back(value); } fprintf(f5,"){"); for (unsigned int i=0; i<orth.size(); i++) { out2->push_back(orth[i]); if (i) fprintf(f5,",%g", orth[i]); else fprintf(f5,"%g", orth[i]); } fprintf(f5,"};\n"); } fprintf(f5,"};\n"); fclose(f5); lsys->clear(); lsys2->clear(); data2->Time.push_back(0); data2->setFileName("orthogonal.pos"); data2->finalize(); #endif } return view; }
void GMSH_SimplePartitionPlugin::run() { #if defined(HAVE_MESH) int numSlicesX = (int)SimplePartitionOptions_Number[0].def; int numSlicesY = (int)SimplePartitionOptions_Number[1].def; int numSlicesZ = (int)SimplePartitionOptions_Number[2].def; int createTopology = (int)SimplePartitionOptions_Number[3].def; std::vector<std::string> exprX(1), exprY(1), exprZ(1); exprX[0] = SimplePartitionOptions_String[0].def; exprY[0] = SimplePartitionOptions_String[1].def; exprZ[0] = SimplePartitionOptions_String[2].def; GModel *m = GModel::current(); if(!m->getNumMeshElements()){ Msg::Error("Plugin(SimplePartition) requires a mesh"); return; } if(numSlicesX < 1 || numSlicesY < 1 || numSlicesZ < 1){ Msg::Error("Number of slices should be strictly positive"); return; } m->unpartitionMesh(); SBoundingBox3d bbox = m->bounds(); double pminX = bbox.min()[0], pmaxX = bbox.max()[0]; double pminY = bbox.min()[1], pmaxY = bbox.max()[1]; double pminZ = bbox.min()[2], pmaxZ = bbox.max()[2]; std::vector<double> ppX(numSlicesX + 1); std::vector<double> ppY(numSlicesY + 1); std::vector<double> ppZ(numSlicesZ + 1); std::vector<std::string> variables(1, "t"); std::vector<double> values(1), res(1); { mathEvaluator f(exprX, variables); for(int p = 0; p <= numSlicesX; p++) { double t = values[0] = (double)p / (double)numSlicesX; if(f.eval(values, res)) t = res[0]; ppX[p] = pminX + t * (pmaxX - pminX); } } bool emptyX = (ppX[0] == ppX[numSlicesX]); { mathEvaluator f(exprY, variables); for(int p = 0; p <= numSlicesY; p++) { double t = values[0] = (double)p / (double)numSlicesY; if(f.eval(values, res)) t = res[0]; ppY[p] = pminY + t * (pmaxY - pminY); } } bool emptyY = (ppY[0] == ppY[numSlicesY]); { mathEvaluator f(exprZ, variables); for(int p = 0; p <= numSlicesZ; p++) { double t = values[0] = (double)p / (double)numSlicesZ; if(f.eval(values, res)) t = res[0]; ppZ[p] = pminZ + t * (pmaxZ - pminZ); } } bool emptyZ = (ppZ[0] == ppZ[numSlicesZ]); std::vector<GEntity *> entities; m->getEntities(entities); hashmap<MElement *, unsigned int> elmToPartition; for(std::size_t i = 0; i < entities.size(); i++) { GEntity *ge = entities[i]; for(std::size_t j = 0; j < ge->getNumMeshElements(); j++) { MElement *e = ge->getMeshElement(j); SPoint3 point = e->barycenter(); int part = 0; for(int kx = 0; kx < numSlicesX; kx++) { if(part) break; for(int ky = 0; ky < numSlicesY; ky++) { if(part) break; for(int kz = 0; kz < numSlicesZ; kz++) { if(part) break; if((emptyX || (kx == 0 && ppX[0] == point[0]) || (ppX[kx] < point[0] && point[0] <= ppX[kx + 1])) && (emptyY || (ky == 0 && ppY[0] == point[1]) || (ppY[ky] < point[1] && point[1] <= ppY[ky + 1])) && (emptyZ || (kz == 0 && ppZ[0] == point[2]) || (ppZ[kz] < point[2] && point[2] <= ppZ[kz + 1]))){ part = kx * numSlicesY * numSlicesZ + ky * numSlicesZ + kz + 1; elmToPartition.insert(std::pair<MElement *, unsigned int>(e, part)); e->setPartition(part); // this will be removed } } } } } } opt_mesh_partition_create_topology(0, GMSH_SET | GMSH_GUI, createTopology); int ier = PartitionUsingThisSplit(m, numSlicesX * numSlicesY * numSlicesZ, elmToPartition); if(!ier) { opt_mesh_color_carousel(0, GMSH_SET | GMSH_GUI, 3.); CTX::instance()->mesh.changed = ENT_ALL; } #else Msg::Error("Gmsh must be compiled with Mesh support to partition meshes"); #endif }
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; }
Mesh::Mesh(const std::map<MElement*,GEntity*> &element2entity, const std::set<MElement*> &els, std::set<MVertex*> &toFix, bool fixBndNodes, bool fastJacEval) : _fastJacEval(fastJacEval) { _dim = (*els.begin())->getDim(); // Initialize elements, vertices, free vertices and element->vertices // connectivity const int nElements = els.size(); _nPC = 0; _el.resize(nElements); _el2FV.resize(nElements); _el2V.resize(nElements); _nBezEl.resize(nElements); _nNodEl.resize(nElements); _indPCEl.resize(nElements); int iEl = 0; bool nonGeoMove = false; for(std::set<MElement*>::const_iterator it = els.begin(); it != els.end(); ++it, ++iEl) { _el[iEl] = *it; const JacobianBasis *jac = _el[iEl]->getJacobianFuncSpace(); _nBezEl[iEl] = _fastJacEval ? jac->getNumJacNodesFast() : jac->getNumJacNodes(); _nNodEl[iEl] = jac->getNumMapNodes(); for (int iVEl = 0; iVEl < jac->getNumMapNodes(); iVEl++) { MVertex *vert = _el[iEl]->getVertex(iVEl); GEntity *ge = vert->onWhat(); const int vDim = ge->dim(); const bool hasParam = ge->haveParametrization(); int iV = addVert(vert); _el2V[iEl].push_back(iV); if ((vDim > 0) && (toFix.find(vert) == toFix.end()) && (!fixBndNodes || vDim == _dim)) { // Free vertex? ParamCoord *param; if (vDim == 3) param = new ParamCoordPhys3D(); else if (hasParam) param = new ParamCoordParent(vert); else { if (vDim == 2) param = new ParamCoordLocalSurf(vert); else param = new ParamCoordLocalLine(vert); nonGeoMove = true; } int iFV = addFreeVert(vert,iV,vDim,param,toFix); _el2FV[iEl].push_back(iFV); for (int i=_startPCFV[iFV]; i<_startPCFV[iFV]+vDim; i++) _indPCEl[iEl].push_back(i); } else _el2FV[iEl].push_back(-1); } } if (nonGeoMove) Msg::Info("WARNING: Some vertices will be moved along local lines " "or planes, they may not remain on the exact geometry"); // Initial coordinates _ixyz.resize(nVert()); for (int iV = 0; iV < nVert(); iV++) _ixyz[iV] = _vert[iV]->point(); _iuvw.resize(nFV()); for (int iFV = 0; iFV < nFV(); iFV++) _iuvw[iFV] = _paramFV[iFV]->getUvw(_freeVert[iFV]); // Set current coordinates _xyz = _ixyz; _uvw = _iuvw; // Set normals to 2D elements (with magnitude of inverse Jacobian) or initial // Jacobians of 3D elements if (_dim == 2) { _scaledNormEl.resize(nEl()); for (int iEl = 0; iEl < nEl(); iEl++) calcScaledNormalEl2D(element2entity,iEl); } else { _invStraightJac.resize(nEl(),1.); double dumJac[3][3]; for (int iEl = 0; iEl < nEl(); iEl++) _invStraightJac[iEl] = 1. / fabs(_el[iEl]->getPrimaryJacobian(0.,0.,0.,dumJac)); } }
// Main function for fast curving void HighOrderMeshFastCurving(GModel *gm, FastCurvingParameters &p) { double t1 = Cpu(); Msg::StatusBar(true, "Optimizing high order mesh..."); std::vector<GEntity*> allEntities; gm->getEntities(allEntities); // Compute vert. -> elt. connectivity Msg::Info("Computing connectivity..."); std::map<MVertex*, std::vector<MElement *> > vertex2elements; for (int iEnt = 0; iEnt < allEntities.size(); ++iEnt) calcVertex2Elements(p.dim, allEntities[iEnt], vertex2elements); // Get BL field (if any) BoundaryLayerField *blf = getBLField(gm); // Build multimap of each geometric entity to its boundaries std::multimap<GEntity*,GEntity*> entities; if (blf) { // BF field? for (int iEnt = 0; iEnt < allEntities.size(); ++iEnt) { GEntity* &entity = allEntities[iEnt]; if (entity->dim() == p.dim && (!p.onlyVisible || entity->getVisibility())) // Consider only "domain" entities if (p.dim == 2) { // "Domain" face? std::list<GEdge*> edges = entity->edges(); for (std::list<GEdge*>::iterator itEd = edges.begin(); itEd != edges.end(); itEd++) // Loop over model boundary edges if (blf->isEdgeBL((*itEd)->tag())) // Already skip model edge if no BL there entities.insert(std::pair<GEntity*,GEntity*>(entity, *itEd)); } else if (p.dim == 3) { // "Domain" region? std::list<GFace*> faces = entity->faces(); for (std::list<GFace*>::iterator itF = faces.begin(); itF != faces.end(); itF++) // Loop over model boundary faces if (blf->isFaceBL((*itF)->tag())) // Already skip model face if no BL there entities.insert(std::pair<GEntity*,GEntity*>(entity, *itF)); } } } else { // No BL field for (int iEnt = 0; iEnt < allEntities.size(); ++iEnt) { GEntity* &entity = allEntities[iEnt]; if (entity->dim() == p.dim-1 && (!p.onlyVisible || entity->getVisibility())) // Consider boundary entities entities.insert(std::pair<GEntity*,GEntity*>(0, entity)); } } // Build normals if necessary std::map<GEntity*, std::map<MVertex*, SVector3> > normVertEnt; // Normal to each vertex for each geom. entity if (!blf) { Msg::Warning("Boundary layer data not found, trying to detect columns"); buildNormals(vertex2elements, entities, p, normVertEnt); } // Loop over geometric entities for (std::multimap<GEntity*,GEntity*>::iterator itBE = entities.begin(); itBE != entities.end(); itBE++) { GEntity *domEnt = itBE->first, *bndEnt = itBE->second; BoundaryLayerColumns *blc = 0; if (blf) { Msg::Info("Curving elements for entity %d bounding entity %d...", bndEnt->tag(), domEnt->tag()); if (p.dim == 2) blc = domEnt->cast2Face()->getColumns(); else if (p.dim == 3) blc = domEnt->cast2Region()->getColumns(); else Msg::Error("Fast curving implemented only in dim. 2 and 3"); } else Msg::Info("Curving elements for boundary entity %d...", bndEnt->tag()); std::map<MVertex*, SVector3> &normVert = normVertEnt[bndEnt]; curveMeshFromBnd(vertex2elements, normVert, blc, bndEnt, p); } double t2 = Cpu(); Msg::StatusBar(true, "Done curving high order mesh (%g s)", t2-t1); }