Beispiel #1
0
// 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));
  }
}
Beispiel #2
0
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();
}
Beispiel #3
0
// 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);
  }
}
Beispiel #4
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);
  }
}
// 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);
}