Example #1
0
static double LC_MVertex_CURV(GEntity *ge, double U, double V)
{
  double Crv = 0;
  switch(ge->dim()){
  case 0:
    Crv = max_edge_curvature((const GVertex *)ge);
    //Crv = std::max(max_surf_curvature_vertex((const GVertex *)ge), Crv);
    // Crv = max_surf_curvature((const GVertex *)ge);
    break;
  case 1:
    {
      GEdge *ged = (GEdge *)ge;
      Crv = ged->curvature(U);
      Crv = std::max(Crv, max_surf_curvature(ged, U));
      // Crv = max_surf_curvature(ged, U);
    }
    break;
  case 2:
    {
      GFace *gf = (GFace *)ge;
      Crv = gf->curvature(SPoint2(U, V));
    }
    break;
  }
  double lc = Crv > 0 ? 2 * M_PI / Crv / CTX::instance()->mesh.minCircPoints : MAX_LC;
  return lc;
}
Example #2
0
// returns the cross field as a pair of othogonal vectors (NOT in parametric coordinates, but real 3D coordinates)
Pair<SVector3, SVector3> frameFieldBackgroundMesh2D::compute_crossfield_directions(double u, double v,
        double angle_current)
{
    // get the unit normal at that point
    GFace *face = dynamic_cast<GFace*>(gf);
    if(!face) {
        Msg::Error("Entity is not a face in background mesh");
        return Pair<SVector3,SVector3>(SVector3(), SVector3());
    }

    Pair<SVector3, SVector3> der = face->firstDer(SPoint2(u,v));
    SVector3 s1 = der.first();
    SVector3 s2 = der.second();
    SVector3 n = crossprod(s1,s2);
    n.normalize();

    SVector3 basis_u = s1;
    basis_u.normalize();
    SVector3 basis_v = crossprod(n,basis_u);

    // normalize vector t1 that is tangent to gf at uv
    SVector3 t1 = basis_u * cos(angle_current) + basis_v * sin(angle_current) ;
    t1.normalize();

    // compute the second direction t2 and normalize (t1,t2,n) is the tangent frame
    SVector3 t2 = crossprod(n,t1);
    t2.normalize();

    return Pair<SVector3,SVector3>(SVector3(t1[0],t1[1],t1[2]),
                                   SVector3(t2[0],t2[1],t2[2]));
}
Example #3
0
// build the BDS from a list of GFace
// This is a TRUE copy
BDS_Mesh *gmsh2BDS(std::list<GFace*> &l)
{
  BDS_Mesh *m = new BDS_Mesh;
  for (std::list<GFace*>::iterator it = l.begin(); it != l.end(); ++it){
    GFace *gf = *it;
    m->add_geom(gf->tag(), 2);
    BDS_GeomEntity *g2 = m->get_geom(gf->tag(), 2);
    for (unsigned int i = 0; i < gf->triangles.size(); i++){
      MTriangle *e = gf->triangles[i];
      BDS_Point *p[3];
      for (int j = 0; j < 3; j++){
        p[j] = m->find_point(e->getVertex(j)->getNum());
        if (!p[j]) {
          p[j] = m->add_point(e->getVertex(j)->getNum(), e->getVertex(j)->x(),
                              e->getVertex(j)->y(), e->getVertex(j)->z());
          SPoint2 param;
          reparamMeshVertexOnFace(e->getVertex(j), gf, param);
          p[j]->u = param[0];
          p[j]->v = param[1];
          m->add_geom(e->getVertex(j)->onWhat()->tag(),
                      e->getVertex(j)->onWhat()->dim());
          BDS_GeomEntity *g = m->get_geom(e->getVertex(j)->onWhat()->tag(),
                                          e->getVertex(j)->onWhat()->dim());
          p[j]->g = g;
        }
      }
      BDS_Face *f = m->add_triangle(p[0]->iD, p[1]->iD, p[2]->iD);
      f->g = g2;
    }
  }
  return m;
}
Example #4
0
GPoint backgroundMesh2D::get_GPoint_from_MVertex(const MVertex *v)const
{
    GFace *face = dynamic_cast<GFace*>(gf);
    if(!face) {
        Msg::Error("Entity is not a face in background mesh");
        return GPoint();
    }
    return face->point(SPoint2(v->x(),v->y()));
}
Example #5
0
void Centerline::run()
{
  double t1 = Cpu();
  if (update_needed){
    std::ifstream input;
    //std::string pattern = FixRelativePath(fileName, "./");
    //Msg::StatusBar(true, "Reading TEST '%s'...", pattern.c_str());
    //input.open(pattern.c_str());
    input.open(fileName.c_str());
    if(StatFile(fileName))
      Msg::Fatal("Centerline file '%s' does not exist ", fileName.c_str());
    importFile(fileName);
    buildKdTree();
    update_needed = false;
  }

  if (is_cut) cutMesh();
  else{
    GFace *gf = current->getFaceByTag(1);
    gf->addPhysicalEntity(1);
    current->setPhysicalName("wall", 2, 1);//tag 1
    current->createTopologyFromMesh();
    NV = current->getMaxElementaryNumber(0);
    NE = current->getMaxElementaryNumber(1);
    NF = current->getMaxElementaryNumber(2);
    NR = current->getMaxElementaryNumber(3);
  }

  //identify the boundary edges by looping over all discreteFaces
  std::vector<GEdge*> boundEdges;
  double dist_inlet = 1.e6;
  GEdge *gin = NULL;
  for (int i= 0; i< NF; i++){
    GFace *gf = current->getFaceByTag(i+1);
    std::list<GEdge*> l_edges = gf->edges();
    for(std::list<GEdge*>::iterator it = l_edges.begin(); it != l_edges.end(); it++){
      std::vector<GEdge*>::iterator ite = std::find(boundEdges.begin(),
                                                    boundEdges.end(), *it);
      if (ite != boundEdges.end()) boundEdges.erase(ite);
      else boundEdges.push_back(*it);
      GVertex *gv = (*it)->getBeginVertex();
      SPoint3 pt(gv->x(), gv->y(), gv->z());
      double dist = pt.distance(ptin);
      if(dist < dist_inlet){
	dist_inlet = dist;
	gin = *it;
      }
    }
  }

  if (is_closed)   createClosedVolume(gin, boundEdges);
  if (is_extruded) extrudeBoundaryLayerWall(gin, boundEdges);

  double t2 = Cpu();
  Msg::Info("Centerline operators computed in %g (s) ",t2-t1);
}
Example #6
0
double distanceToGeometry(GModel *gm, int dim, int tag, int distType,
                          double tol, int meshDiscr, int geomDiscr)
{
  double maxDist = 0.;

  if (dim == 2) {
    GEdge *ge = gm->getEdgeByTag(tag);
    if (ge->geomType() == GEntity::Line) return 0.;
    for (unsigned int i = 0; i < ge->lines.size(); i++) {
      double dist;
      switch (distType) {
        case CADDIST_TAYLOR:
          dist = taylorDistanceEdge(ge->lines[i], ge);
          break;
        case CADDIST_FRECHET:
          dist = discreteFrechetDistanceEdge(ge->lines[i], ge,
                                             tol, meshDiscr, geomDiscr);
          break;
        case CADDIST_HAUSFAST:
          dist = discreteHausdorffDistanceFastEdge(ge->lines[i], ge,
                                                   tol, meshDiscr, geomDiscr);
          break;
        case CADDIST_HAUSBRUTE:
          dist = discreteHausdorffDistanceBruteEdge(ge->lines[i], ge,
                                                    tol, meshDiscr, geomDiscr);
          break;
        default:
          Msg::Error("Wrong CAD distance type in distanceToGeometry");
          return -1.;
          break;
      }
      maxDist = std::max(dist, maxDist);
    }
  }
  else if (dim == 3) {
    if (distType == CADDIST_TAYLOR) {
      GFace *gf = gm->getFaceByTag(tag);
      if (gf->geomType() == GEntity::Plane) return 0.;
      for (unsigned int i = 0; i < gf->triangles.size(); i++)
        maxDist = std::max(taylorDistanceFace(gf->triangles[i], gf), maxDist);
      for (unsigned int i = 0; i < gf->quadrangles.size(); i++)
        maxDist = std::max(taylorDistanceFace(gf->quadrangles[i], gf), maxDist);
    }
    else {
      Msg::Error("CAD distance type %i not implemented for surfaces", distType);
      return -1.;
    }
  }
  else {
    Msg::Error("CAD distance cannot be computed for dimension %i", dim);
    return -1.;
  }

  return maxDist;
}
Example #7
0
void Centerline::importFile(std::string fileName)
{
  current = GModel::current();
  std::vector<GFace*> currentFaces(current->firstFace(), current->lastFace());
  for (unsigned int i = 0; i < currentFaces.size(); i++){
    GFace *gf = currentFaces[i];
     if (gf->geomType() == GEntity::DiscreteSurface){
     	for(unsigned int j = 0; j < gf->triangles.size(); j++)
     	  triangles.push_back(gf->triangles[j]);
	if (is_cut){
	  gf->triangles.clear();
	  gf->deleteVertexArrays();
	  current->remove(gf);
	}
     }
  }

  if(triangles.empty()){
    Msg::Error("Current GModel has no triangles ...");
    return;
  }

  mod = new GModel();
  mod->load(fileName);
  mod->removeDuplicateMeshVertices(1.e-8);
  current->setAsCurrent();
  current->setVisibility(1);

  int maxN = 0.0;
  std::vector<GEdge*> modEdges(mod->firstEdge(), mod->lastEdge());
  MVertex *vin = modEdges[0]->lines[0]->getVertex(0);
  ptin = SPoint3(vin->x(), vin->y(), vin->z());
  for (unsigned int i = 0; i < modEdges.size(); i++){
    GEdge *ge = modEdges[i];
    for(unsigned int j = 0; j < ge->lines.size(); j++){
      MLine *l = ge->lines[j];
      MVertex *v0 = l->getVertex(0);
      MVertex *v1 = l->getVertex(1);
      std::map<MVertex*, int>::iterator it0 = colorp.find(v0);
      std::map<MVertex*, int>::iterator it1 = colorp.find(v1);
      if (it0 == colorp.end() || it1 == colorp.end()){
	lines.push_back(l);
	colorl.insert(std::make_pair(l, ge->tag()));
	maxN = std::max(maxN, ge->tag());
       }
      if (it0 == colorp.end()) colorp.insert(std::make_pair(v0, ge->tag()));
      if (it1 == colorp.end()) colorp.insert(std::make_pair(v1, ge->tag()));
    }
 }

  createBranches(maxN);
}
Example #8
0
void Centerline::createSplitCompounds()
{
  //number of discrete vertices, edges, faces and regions for the mesh
  NV = current->getMaxElementaryNumber(0);
  NE = current->getMaxElementaryNumber(1);
  NF = current->getMaxElementaryNumber(2);
  NR = current->getMaxElementaryNumber(3);

  // Remesh new faces (Compound Lines and Compound Surfaces)
  Msg::Info("Centerline: creating split compounds ...");

  //Parametrize Compound Lines
  for (int i=0; i < NE; i++){
    std::vector<GEdge*>e_compound;
    GEdge *pe = current->getEdgeByTag(i+1);//current edge
    e_compound.push_back(pe);
    int num_gec = NE+i+1;
    Msg::Info("Create Compound Line (%d) = %d discrete edge",
              num_gec, pe->tag());
    GEdge *gec =  current->addCompoundEdge(e_compound,num_gec);
    if (CTX::instance()->mesh.algo2d != ALGO_2D_BAMG){
      gec->meshAttributes.method = MESH_TRANSFINITE;
      gec->meshAttributes.nbPointsTransfinite = nbPoints+1;
      gec->meshAttributes.typeTransfinite = 0;
      gec->meshAttributes.coeffTransfinite = 1.0;
    }
  }

  // Parametrize Compound surfaces
  std::list<GEdge*> U0;
  for (int i=0; i < NF; i++){
    std::vector<GFace*> f_compound;
    GFace *pf =  current->getFaceByTag(i+1);//current face
    f_compound.push_back(pf);
    int num_gfc = NF+i+1;
    Msg::Info("Create Compound Surface (%d) = %d discrete face",
              num_gfc, pf->tag());

    //1=conf_spectral 4=convex_circle, 7=conf_fe
    GFace *gfc = current->addCompoundFace(f_compound, 7, 0, num_gfc);

    gfc->meshAttributes.recombine = recombine;
    gfc->addPhysicalEntity(1);
    current->setPhysicalName("wall", 2, 1);//tag 1

  }
}
Example #9
0
gmshRegion::gmshRegion(GModel *m, ::Volume *volume)
  : GRegion(m, volume->Num), v(volume)
{
  for(int i = 0; i < List_Nbr(v->Surfaces); i++){
    Surface *s;
    List_Read(v->Surfaces, i, &s);
    int ori;
    List_Read(v->SurfacesOrientations, i, &ori);
    GFace *f = m->getFaceByTag(abs(s->Num));
    if(f){
      l_faces.push_back(f);
      l_dirs.push_back(ori);
      f->addRegion(this);
    }
    else
      Msg::Error("Unknown surface %d", s->Num);
  }
  for(int i = 0; i < List_Nbr(v->SurfacesByTag); i++){
    int is;
    List_Read(v->SurfacesByTag, i, &is);
    GFace *f = m->getFaceByTag(abs(is));
    if(f){
      l_faces.push_back(f);
      l_dirs.push_back(sign(is));
      f->addRegion(this);
    }
    else
      Msg::Error("Unknown surface %d", is);
  }
  if(v->EmbeddedSurfaces){
    for(int i = 0; i < List_Nbr(v->EmbeddedSurfaces); i++){
      Surface *s;
      List_Read(v->EmbeddedSurfaces, i, &s);
      GFace *gf = m->getFaceByTag(abs(s->Num));
      if(gf)
	addEmbeddedFace(gf);
      else
	Msg::Error("Unknown surface %d", s->Num);
    }
  }
  resetMeshAttributes();
}
Example #10
0
void Centerline::createClosedVolume(GEdge *gin, std::vector<GEdge*> boundEdges)
{
  current->setFactory("Gmsh");
  std::vector<std::vector<GFace *> > myFaceLoops;
  std::vector<GFace *> myFaces;
  for (unsigned int i = 0; i<  boundEdges.size(); i++){
    std::vector<std::vector<GEdge *> > myEdgeLoops;
    std::vector<GEdge *> myEdges;
    GEdge * gec;
    if(is_cut) gec = current->getEdgeByTag(NE+boundEdges[i]->tag());
    else gec = current->getEdgeByTag(boundEdges[i]->tag());
    myEdges.push_back(gec);
    myEdgeLoops.push_back(myEdges);
    GFace *newFace = current->addPlanarFace(myEdgeLoops);
    if (gin==boundEdges[i]) {
      newFace->addPhysicalEntity(2);
      current->setPhysicalName("inlet", 2, 2);//tag 2
    }
    else{
      newFace->addPhysicalEntity(3);
      current->setPhysicalName("outlets", 2, 3);//tag 3
    }
    myFaces.push_back(newFace);
  }

  Msg::Info("Centerline: action (closeVolume) has created %d in/out planar faces ",
            (int)boundEdges.size());

  for (int i = 0; i < NF; i++){
    GFace * gf;
    if(is_cut) gf = current->getFaceByTag(NF+i+1);
    else gf = current->getFaceByTag(i+1);
    myFaces.push_back(gf);
  }
  myFaceLoops.push_back(myFaces);
  GRegion *reg = current->addVolume(myFaceLoops);
  reg->addPhysicalEntity(reg->tag());
  current->setPhysicalName("lumenVolume", 3, reg->tag());

  Msg::Info("Centerline: action (closeVolume) has created volume %d ", reg->tag());

}
Example #11
0
void OCCRegion::setup()
{
  l_faces.clear();
  TopExp_Explorer exp2, exp3;
  for(exp2.Init(s, TopAbs_SHELL); exp2.More(); exp2.Next()){
    TopoDS_Shape shell = exp2.Current();
    Msg::Debug("OCC Region %d - New Shell",tag());
    for(exp3.Init(shell, TopAbs_FACE); exp3.More(); exp3.Next()){
      TopoDS_Face face = TopoDS::Face(exp3.Current());
      GFace *f = model()->getOCCInternals()->getOCCFaceByNativePtr(model(),face);
      if(f){
        l_faces.push_back(f);
        f->addRegion(this);
      }
      else
        Msg::Error("Unknown face in region %d", tag());
    }
  }
  Msg::Debug("OCC Region %d with %d faces", tag(), l_faces.size());
}
Example #12
0
void Mesh::approximationErrorAndGradients(int iEl, double &f, std::vector<double> &gradF, double eps,
					  simpleFunction<double> &fct)
{
  std::vector<SPoint3> _xyz_temp;
  for (int iV = 0; iV < nVert(); iV++){
    _xyz_temp.push_back(SPoint3( _vert[iV]->x(), _vert[iV]->y(), _vert[iV]->z()));
    _vert[iV]->setXYZ(_xyz[iV].x(),_xyz[iV].y(),_xyz[iV].z());
  }

  MElement *element = _el[iEl];

  f = approximationError (fct, element);
  // FIME
  //  if (iEl < 1)printf("approx error elem %d = %g\n",iEl,f);
  int currentId = 0;
  // compute the size of the gradient
  // depends on how many dofs exist per vertex (0,1,2 or 3)
  for (size_t i = 0; i < element->getNumVertices(); ++i) {
    if (_el2FV[iEl][i] >= 0) {// some free coordinates
      currentId += _nPCFV[_el2FV[iEl][i]];
    }
  }
  gradF.clear();
  gradF.resize(currentId, 0.);
  currentId = 0;
  for (size_t i = 0; i < element->getNumVertices(); ++i) {
    if (_el2FV[iEl][i] >= 0) {// some free coordinates
      MVertex *v =  element->getVertex(i);
      // vertex classified on a model edge
      if (_nPCFV[_el2FV[iEl][i]] == 1){
	double t = _uvw[_el2FV[iEl][i]].x();
	GEdge *ge = (GEdge*)v->onWhat();
	SPoint3 p (v->x(),v->y(),v->z());
	GPoint d = ge->point(t+eps);
	v->setXYZ(d.x(),d.y(),d.z());
	double f_d = approximationError (fct, element);
	gradF[currentId++] = (f_d-f)/eps;
	if (iEl < 1)printf("df = %g\n",(f_d-f)/eps);
	v->setXYZ(p.x(),p.y(),p.z());
      }
      else if (_nPCFV[_el2FV[iEl][i]] == 2){
	double uu = _uvw[_el2FV[iEl][i]].x();
	double vv = _uvw[_el2FV[iEl][i]].y();
	GFace *gf = (GFace*)v->onWhat();
	SPoint3 p (v->x(),v->y(),v->z());
	GPoint  d = gf->point(uu+eps,vv);
	v->setXYZ(d.x(),d.y(),d.z());
	double f_u = approximationError (fct, element);
	gradF[currentId++] = (f_u-f)/eps;
	d = gf->point(uu,vv+eps);
	v->setXYZ(d.x(),d.y(),d.z());
	double f_v = approximationError (fct, element);
	gradF[currentId++] = (f_v-f)/eps;
	v->setXYZ(p.x(),p.y(),p.z());
	//	if (iEl < 1)printf("df = %g %g\n",(f_u-f)/eps,(f_v-f)/eps);
      }
    }
  }
  for (int iV = 0; iV < nVert(); iV++)
    _vert[iV]->setXYZ(_xyz_temp[iV].x(),_xyz_temp[iV].y(),_xyz_temp[iV].z());

}
Example #13
0
int GModel::writeDIFF(const std::string &name, bool binary, bool saveAll,
                      double scalingFactor)
{
  if(binary){
    Msg::Error("Binary DIFF output is not implemented");
    return 0;
  }

  FILE *fp = Fopen(name.c_str(), binary ? "wb" : "w");
  if(!fp){
    Msg::Error("Unable to open file '%s'", name.c_str());
    return 0;
  }

  if(noPhysicalGroups()) saveAll = true;

  // get the number of vertices and index the vertices in a continuous
  // sequence
  int numVertices = indexMeshVertices(saveAll);

  // tag the vertices according to which surface they belong to (Note
  // that we use a brute force approach here, so that we can deal with
  // models with incomplete topology. For example, when we merge 2 STL
  // triangulations we don't have the boundary information between the
  // faces, and the vertices would end up categorized on either one.)
  std::vector<std::list<int> > vertexTags(numVertices);
  std::list<int> boundaryIndicators;
  for(riter it = firstRegion(); it != lastRegion(); it++){
    std::list<GFace*> faces = (*it)->faces();
    for(std::list<GFace*>::iterator itf = faces.begin(); itf != faces.end(); itf++){
      GFace *gf = *itf;
      boundaryIndicators.push_back(gf->tag());
      for(unsigned int i = 0; i < gf->getNumMeshElements(); i++){
        MElement *e = gf->getMeshElement(i);
        for(int j = 0; j < e->getNumVertices(); j++){
          MVertex *v = e->getVertex(j);
          if(v->getIndex() > 0)
            vertexTags[v->getIndex() - 1].push_back(gf->tag());
        }
      }
    }
  }
  boundaryIndicators.sort();
  boundaryIndicators.unique();
  for(int i = 0; i < numVertices; i++){
    vertexTags[i].sort();
    vertexTags[i].unique();
  }

  // get all the entities in the model
  std::vector<GEntity*> entities;
  getEntities(entities);

  // find max dimension of mesh elements we need to save
  int dim = 0;
  for(unsigned int i = 0; i < entities.size(); i++)
    if(entities[i]->physicals.size() || saveAll)
      for(unsigned int j = 0; j < entities[i]->getNumMeshElements(); j++)
        dim = std::max(dim, entities[i]->getMeshElement(j)->getDim());

  // loop over all elements we need to save
  int numElements = 0, maxNumNodesPerElement = 0;
  for(unsigned int i = 0; i < entities.size(); i++){
    if(entities[i]->physicals.size() || saveAll){
      for(unsigned int j = 0; j < entities[i]->getNumMeshElements(); j++){
        MElement *e = entities[i]->getMeshElement(j);
        if(e->getStringForDIFF() && e->getDim() == dim){
          numElements++;
          maxNumNodesPerElement = std::max(maxNumNodesPerElement, e->getNumVertices());
        }
      }
    }
  }

  fprintf(fp, "\n\n");
  fprintf(fp, " Finite element mesh (GridFE):\n\n");
  fprintf(fp, " Number of space dim. =   3\n");
  fprintf(fp, " Number of elements   =  %d\n", numElements);
  fprintf(fp, " Number of nodes      =  %d\n\n", numVertices);
  fprintf(fp, " All elements are of the same type : dpTRUE\n");
  fprintf(fp, " Max number of nodes in an element: %d \n", maxNumNodesPerElement);
  fprintf(fp, " Only one subdomain               : dpFALSE\n");
  fprintf(fp, " Lattice data                     ? 0\n\n\n\n");
  fprintf(fp, " %d Boundary indicators:  ", (int)boundaryIndicators.size());
  for(std::list<int>::iterator it = boundaryIndicators.begin();
      it != boundaryIndicators.end(); it++)
    fprintf(fp, " %d", *it);

  fprintf(fp, "\n\n\n");
  fprintf(fp,"  Nodal coordinates and nodal boundary indicators,\n");
  fprintf(fp,"  the columns contain:\n");
  fprintf(fp,"   - node number\n");
  fprintf(fp,"   - coordinates\n");
  fprintf(fp,"   - no of boundary indicators that are set (ON)\n");
  fprintf(fp,"   - the boundary indicators that are set (ON) if any.\n");
  fprintf(fp,"#\n");

  // write mesh vertices
  for(unsigned int i = 0; i < entities.size(); i++){
    for(unsigned int j = 0; j < entities[i]->mesh_vertices.size(); j++){
      MVertex *v = entities[i]->mesh_vertices[j];
      if(v->getIndex() > 0){
        v->writeDIFF(fp, binary, scalingFactor);
        fprintf(fp, " [%d] ", (int)vertexTags[v->getIndex() - 1].size());
        for(std::list<int>::iterator it = vertexTags[v->getIndex() - 1].begin();
            it != vertexTags[v->getIndex() - 1].end(); it++)
          fprintf(fp," %d ", *it);
        fprintf(fp,"\n");
      }
    }
  }

  fprintf(fp, "\n");
  fprintf(fp, "\n");
  fprintf(fp,     "  Element types and connectivity\n");
  fprintf(fp,     "  the columns contain:\n");
  fprintf(fp,     "   - element number\n");
  fprintf(fp,     "   - element type\n");
  fprintf(fp,     "   - subdomain number \n");
  fprintf(fp,     "   - the global node numbers of the nodes in the element.\n");
  fprintf(fp,     "#\n");

  // write mesh elements
  int num = 0;
  for(unsigned int i = 0; i < entities.size(); i++){
    if(entities[i]->physicals.size() || saveAll){
      for(unsigned int j = 0; j < entities[i]->getNumMeshElements(); j++){
        MElement *e = entities[i]->getMeshElement(j);
        if(e->getStringForDIFF() && e->getDim() == dim)
          e->writeDIFF(fp, ++num, binary, entities[i]->tag());
      }
    }
  }
  fprintf(fp, "\n");

  fclose(fp);
  return 1;
}
Example #14
0
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;
}
Example #15
0
void frameFieldBackgroundMesh2D::computeCrossField(simpleFunction<double> &eval_diffusivity)
{
    angles.clear();

    DoubleStorageType _cosines4,_sines4;

    list<GEdge*> e;
    GFace *face = dynamic_cast<GFace*>(gf);
    if(!face) {
        Msg::Error("Entity is not a face in background mesh");
        return;
    }

    replaceMeshCompound(face, e);

    list<GEdge*>::const_iterator it = e.begin();

    for( ; it != e.end(); ++it ) {
        if (!(*it)->isSeam(face)) {
            for(unsigned int i = 0; i < (*it)->lines.size(); i++ ) {
                MVertex *v[2];
                v[0] = (*it)->lines[i]->getVertex(0);
                v[1] = (*it)->lines[i]->getVertex(1);
                SPoint2 p1,p2;
                reparamMeshEdgeOnFace(v[0],v[1],face,p1,p2);
                Pair<SVector3, SVector3> der = face->firstDer((p1+p2)*.5);
                SVector3 t1 = der.first();
                SVector3 t2 = der.second();
                SVector3 n = crossprod(t1,t2);
                n.normalize();
                SVector3 d1(v[1]->x()-v[0]->x(),v[1]->y()-v[0]->y(),v[1]->z()-v[0]->z());
                t1.normalize();
                d1.normalize();
                double _angle = myAngle (t1,d1,n);
                normalizeAngle (_angle);
                for (int i=0; i<2; i++) {
                    DoubleStorageType::iterator itc = _cosines4.find(v[i]);
                    DoubleStorageType::iterator its = _sines4.find(v[i]);
                    if (itc != _cosines4.end()) {
                        itc->second  = 0.5*(itc->second + cos(4*_angle));
                        its->second  = 0.5*(its->second + sin(4*_angle));
                    }
                    else {
                        _cosines4[v[i]] = cos(4*_angle);
                        _sines4[v[i]] = sin(4*_angle);
                    }
                }
            }
        }
    }

    propagateValues(_cosines4,eval_diffusivity,false);
    propagateValues(_sines4,eval_diffusivity,false);

    std::map<MVertex*,MVertex*>::iterator itv2 = _2Dto3D.begin();
    for ( ; itv2 != _2Dto3D.end(); ++itv2) {
        MVertex *v_2D = itv2->first;
        MVertex *v_3D = itv2->second;
        double angle = atan2(_sines4[v_3D],_cosines4[v_3D]) / 4.0;
        normalizeAngle (angle);
        angles[v_2D] = angle;
    }
}
Example #16
0
void Filler::treat_region(GRegion* gr){

  int NumSmooth = CTX::instance()->mesh.smoothCrossField;
  std::cout << "NumSmooth = " << NumSmooth << std::endl ;
  if(NumSmooth && (gr->dim() == 3)){
    double scale = gr->bounds().diag()*1e-2;
    Frame_field::initRegion(gr,NumSmooth);
    Frame_field::saveCrossField("cross0.pos",scale);

    Frame_field::smoothRegion(gr,NumSmooth);
    Frame_field::saveCrossField("cross1.pos",scale);
  }

#if defined(HAVE_RTREE)
  unsigned int i;
  int j;
  int count;
  int limit;
  bool ok2;
  double x,y,z;
  SPoint3 point;
  Node *node,*individual,*parent;
  MVertex* vertex;
  MElement* element;
  MElementOctree* octree;
  deMeshGRegion deleter;
  Wrapper wrapper;
  GFace* gf;
  std::queue<Node*> fifo;
  std::vector<Node*> spawns;
  std::vector<Node*> garbage;
  std::vector<MVertex*> boundary_vertices;
  std::set<MVertex*> temp;
  std::list<GFace*> faces;
  std::map<MVertex*,int> limits;
  std::set<MVertex*>::iterator it;
  std::list<GFace*>::iterator it2;
  std::map<MVertex*,int>::iterator it3;
  RTree<Node*,double,3,double> rtree;
  
  Frame_field::init_region(gr);
  Size_field::init_region(gr);
  Size_field::solve(gr);
  octree = new MElementOctree(gr->model());
  garbage.clear();
  boundary_vertices.clear();
  temp.clear();
  new_vertices.clear();
  faces.clear();
  limits.clear();

  faces = gr->faces();	
  for(it2=faces.begin();it2!=faces.end();it2++){
    gf = *it2;
	limit = code(gf->tag());
	for(i=0;i<gf->getNumMeshElements();i++){
	  element = gf->getMeshElement(i);
      for(j=0;j<element->getNumVertices();j++){
	    vertex = element->getVertex(j);
		temp.insert(vertex);
		limits.insert(std::pair<MVertex*,int>(vertex,limit));
	  }
	}
  }
		
  /*for(i=0;i<gr->getNumMeshElements();i++){
    element = gr->getMeshElement(i);
    for(j=0;j<element->getNumVertices();j++){
      vertex = element->getVertex(j);
      temp.insert(vertex);
    }
  }*/

  for(it=temp.begin();it!=temp.end();it++){
    if((*it)->onWhat()->dim()==0){
	  boundary_vertices.push_back(*it);
	}
  }
	
  for(it=temp.begin();it!=temp.end();it++){
    if((*it)->onWhat()->dim()==1){
	  boundary_vertices.push_back(*it);
	}
  }
	
  for(it=temp.begin();it!=temp.end();it++){
    if((*it)->onWhat()->dim()==2){
	  boundary_vertices.push_back(*it);
	}
  }
	
  /*for(it=temp.begin();it!=temp.end();it++){
    if((*it)->onWhat()->dim()<3){
      boundary_vertices.push_back(*it);
    }
  }*/
  //std::ofstream file("nodes.pos");
  //file << "View \"test\" {\n";	

  for(i=0;i<boundary_vertices.size();i++){
    x = boundary_vertices[i]->x();
    y = boundary_vertices[i]->y();
    z = boundary_vertices[i]->z();
    
    node = new Node(SPoint3(x,y,z));
    compute_parameters(node,gr);
	node->set_layer(0);
	
	it3 = limits.find(boundary_vertices[i]);
	node->set_limit(it3->second);
	
	rtree.Insert(node->min,node->max,node);
	fifo.push(node);
    //print_node(node,file);
  }
  
  count = 1;
  while(!fifo.empty()){
    parent = fifo.front();
	fifo.pop();
	garbage.push_back(parent);
	  
	if(parent->get_limit()!=-1 && parent->get_layer()>=parent->get_limit()){
	  continue;
	}
	  
	spawns.clear();
	spawns.resize(6);
	  
	for(i=0;i<6;i++){
	  spawns[i] = new Node();
	}
	
	create_spawns(gr,octree,parent,spawns);
	
	for(i=0;i<6;i++){
	  ok2 = 0;
	  individual = spawns[i];
	  point = individual->get_point();
	  x = point.x();
	  y = point.y();
	  z = point.z();
	  
	  if(inside_domain(octree,x,y,z)){
		compute_parameters(individual,gr);
		individual->set_layer(parent->get_layer()+1);
		individual->set_limit(parent->get_limit());
		
		if(far_from_boundary(octree,individual)){
		  wrapper.set_ok(1);
		  wrapper.set_individual(individual);
		  wrapper.set_parent(parent);
		  rtree.Search(individual->min,individual->max,rtree_callback,&wrapper);
			
		  if(wrapper.get_ok()){
		    fifo.push(individual);
		    rtree.Insert(individual->min,individual->max,individual);
			vertex = new MVertex(x,y,z,gr,0);
			new_vertices.push_back(vertex);
			ok2 = 1;
			//print_segment(individual->get_point(),parent->get_point(),file);
		  }
	    }
	  }
		
	  if(!ok2) delete individual;
	}
	
	if(count%100==0){
	  printf("%d\n",count);
	}
	count++;
  }
  
  //file << "};\n";

  int option = CTX::instance()->mesh.algo3d;
  CTX::instance()->mesh.algo3d = ALGO_3D_DELAUNAY;

  deleter(gr);
  std::vector<GRegion*> regions;
  regions.push_back(gr);
  meshGRegion mesher(regions); //?
  mesher(gr); //?
  MeshDelaunayVolume(regions);

  CTX::instance()->mesh.algo3d = option;
	
  for(i=0;i<garbage.size();i++) delete garbage[i];
  for(i=0;i<new_vertices.size();i++) delete new_vertices[i];
  new_vertices.clear();
  delete octree;
  rtree.RemoveAll();
  Size_field::clear();
  Frame_field::clear();
#endif
}
Example #17
0
bool computeFourNeighbors (frameFieldBackgroundMesh2D *bgm,
                           MVertex *v_center, // the vertex for which we want to
                                              // generate 4 neighbors (real
                                              // vertex (xyz), not parametric!)
                           SPoint2 &midpoint,
                           bool goNonLinear, // do we compute the position in
                                             // the real surface which is
                                             // nonlinear
                           SPoint2 newP[4][NUMDIR], // look into other directions
                           SMetric3 &metricField) // the mesh metric
{
  // we assume that v is on surface gf, and backgroundMesh2D has been created based on gf

  // get BGM and GFace
  GFace *gf = dynamic_cast<GFace*>(bgm->getBackgroundGEntity());

  // get the parametric coordinates of the point on the surface
  reparamMeshVertexOnFace(v_center, gf, midpoint);

  // get RK info on midpoint (infos in two directions...)
  RK_form infos;
  bgm->compute_RK_infos(midpoint[0],midpoint[1],v_center->x(), v_center->y(),
                        v_center->z(), infos);
  metricField = infos.metricField;

  // shoot in four directions
  SPoint2 param_vec;
  double h;
  for (int i=0;i<4;i++){// in four directions
    switch (i){
    case 0:
      param_vec = infos.paramt1;
      h = infos.paramh.first;
      break;
    case 1:
      param_vec = infos.paramt2;
      h = infos.paramh.second;
      break;
    case 2:
      param_vec = infos.paramt1 * -1.;
      h = infos.paramh.first;
      break;
    case 3:
      param_vec = infos.paramt2 * -1.;
      h = infos.paramh.second;
      break;
    }
    shoot(midpoint,param_vec,h,newP[i][0]);
    //    cout << "(" << midpoint[0] << "," <<midpoint[1] << ") -> (" <<
    //    newP[i][0][0] << "," << newP[i][0][1] << ") " << endl;
  }

  // the following comes from surfaceFiller.cpp...
  const double EPS = 1.e-7;
  for (int j=0;j<2;j++){
    for (int i=0;i<4;i++){
      newP[i][0][j] += (EPS* (double)rand() / RAND_MAX);
    }
  }

  // We could stop here. Yet, if the metric varies a lot, we can solve a
  // nonlinear problem in order to find a better approximation in the real
  // surface
  if (1 && goNonLinear){
    double L = infos.localsize;
    double newPoint[4][2];
    for (int j=0;j<2;j++){
      for (int i=0;i<4;i++){
        newPoint[i][j] = newP[i][0][j];
      }
    }
    double ERR[4];
    for (int i=0;i<4;i++){                                              //
      //      if (newPoint[i][0] < rangeU.low())newPoint[i][0] = rangeU.low();
      //      if (newPoint[i][0] > rangeU.high())newPoint[i][0] = rangeU.high();
      //      if (newPoint[i][1] < rangeV.low())newPoint[i][1] = rangeV.low();
      //      if (newPoint[i][1] > rangeV.high())newPoint[i][1] = rangeV.high();
      GPoint pp = gf->point(newP[i][0]);
      double D = sqrt ((pp.x() - v_center->x())*(pp.x() - v_center->x()) +
                       (pp.y() - v_center->y())*(pp.y() - v_center->y()) +
                       (pp.z() - v_center->z())*(pp.z() - v_center->z()) );
      ERR[i] = 100*fabs(D-L)/(D+L);
      //      printf("L = %12.5E D = %12.5E ERR = %12.5E\n",L,D,100*fabs(D-L)/(D+L));
    }

    surfaceFunctorGFace ss (gf);
    SVector3 dirs[4] = {infos.t1*(-1.0),infos.t2*(-1.0),infos.t1*(1.0),infos.t2*(1.0)};
    for (int i=0;i<4;i++){
      if (ERR[i] > 12){
        double uvt[3] = {newPoint[i][0],newPoint[i][1],0.0};
        // printf("Intersecting with circle N = %g %g %g dir = %g %g %g R
        //	  = %g p = %g %g
        //	  %g\n",n.x(),n.y(),n.z(),dirs[i].x(),dirs[i].y(),dirs[i].z(),L,
        //        v_center->x(),v_center->y(),v_center->z());
        curveFunctorCircle cf (dirs[i],infos.normal,
                               SVector3(v_center->x(),v_center->y(),v_center->z()), L);
        if (intersectCurveSurface (cf,ss,uvt,infos.paramh.first*1.e-3)){
          GPoint pp = gf->point(SPoint2(uvt[0],uvt[1]));
          double D = sqrt ((pp.x() - v_center->x())*(pp.x() - v_center->x()) +
                           (pp.y() - v_center->y())*(pp.y() - v_center->y()) +
                           (pp.z() - v_center->z())*(pp.z() - v_center->z()) );
          double DP = sqrt ((newPoint[i][0]-uvt[0])*(newPoint[i][0]-uvt[0]) +
                            (newPoint[i][1]-uvt[1])*(newPoint[i][1]-uvt[1]));
          double newErr = 100*fabs(D-L)/(D+L);
          //	    if (v_center->onWhat() != gf && gf->tag() == 3){
          //	      crossField2d::normalizeAngle (uvt[2]);
          //	      printf("INTERSECT angle = %g DP %g\n",uvt[2],DP);
          //	    }
          if (newErr < 1 && DP < .1){
            //	      printf("%12.5E vs %12.5E : %12.5E %12.5E vs %12.5E %12.5E
            //	      \n",ERR[i],newErr,newPoint[i][0],newPoint[i][1],uvt[0],uvt[1]);
            newPoint[i][0] = uvt[0];
            newPoint[i][1] = uvt[1];
          }
          //	    printf("OK\n");
        }
        else{
          Msg::Debug("Cannot put a new point on Surface %d",gf->tag());
          // printf("NOT OK\n");
        }
      }
    }

    // return the four new vertices
    for (int i=0;i<4;i++){
      newP[i][0] = SPoint2(newPoint[i][0],newPoint[i][1]);
    }
  }

  return true;
}
Example #18
0
bool Filler3D::treat_region(GRegion *gr)
{
  BGMManager::set_use_cross_field(true);

  bool use_vectorial_smoothness;
  bool use_fifo;
  string algo;

  // readValue("param.dat","SMOOTHNESSALGO",algo);
  algo.assign("SCALAR");

  if (!algo.compare("SCALAR")){
    use_vectorial_smoothness = false;
    use_fifo = false;
  }
  else if (!algo.compare("FIFO")){
    use_vectorial_smoothness = false;
    use_fifo = true;
  }
  else{
    cout << "unknown SMOOTHNESSALGO !" << endl;
    throw;
  }

  const bool debug=false;
  const bool export_stuff=true;
  double a;

  cout << "ENTERING POINTINSERTION3D" << endl;

  // acquire background mesh
  cout << "pointInsertion3D: recover BGM" << endl;
  a = Cpu();
  frameFieldBackgroundMesh3D *bgm =
    dynamic_cast<frameFieldBackgroundMesh3D*>(BGMManager::get(gr));
  time_smoothing += (Cpu() - a);

  if (!bgm){
    cout << "pointInsertion3D:: BGM dynamic cast failed ! " << endl;
    throw;
  }

  // export BGM fields
  if(export_stuff){
    cout << "pointInsertion3D: export size field " << endl;
    stringstream ss;
    ss << "bg3D_sizefield_" << gr->tag() << ".pos";
    bgm->exportSizeField(ss.str());

    cout << "pointInsertion3D : export crossfield " << endl;
    stringstream sscf;
    sscf << "bg3D_crossfield_" << gr->tag() << ".pos";
    bgm->exportCrossField(sscf.str());

    cout << "pointInsertion3D : export smoothness " << endl;
    stringstream sss;
    sss << "bg3D_smoothness_" << gr->tag() << ".pos";
    bgm->exportSmoothness(sss.str());

    if (use_vectorial_smoothness){
      cout << "pointInsertion3D : export vectorial smoothness " << endl;
      stringstream ssvs;
      ssvs << "bg3D_vectorial_smoothness_" << gr->tag() << ".pos";
      bgm->exportVectorialSmoothness(ssvs.str());
    }
  }

  // ---------------- START FILLING NEW POINTS ----------------
  cout << "pointInsertion3D : inserting points in region " << gr->tag()  << endl;

  //ProfilerStart("/home/bernard/profile");
  a = Cpu();

  // ----- initialize fifo list -----

  RTree<MVertex*,double,3,double> rtree;
  listOfPoints *fifo;
  if (use_fifo)
    fifo = new listOfPointsFifo();
  else if (use_vectorial_smoothness)
    fifo = new listOfPointsVectorialSmoothness();
  else
    fifo = new listOfPointsScalarSmoothness();

  set<MVertex*> temp;
  vector<MVertex*> boundary_vertices;
  map<MVertex*,int> vert_priority;
  map<MVertex*,double> smoothness_forplot;
  MElement *element;
  MVertex *vertex;
  list<GFace*> faces = gr->faces();
  for(list<GFace*>::iterator it=faces.begin();it!=faces.end();it++){// for all faces
    GFace *gf = *it;
    // int limit = code_kesskessai(gf->tag());
    for(unsigned int i=0;i<gf->getNumMeshElements();i++){
      element = gf->getMeshElement(i);
      for(int j=0;j<element->getNumVertices();j++){// for all vertices
        vertex = element->getVertex(j);
        temp.insert(vertex);
        // limits.insert(make_pair(vertex,limit));
      }
    }
  }

  int geodim;
  for(set<MVertex*>::iterator it=temp.begin();it!=temp.end();it++){
    geodim = (*it)->onWhat()->dim();
    if ((geodim==0) || (geodim==1) || (geodim==2)) boundary_vertices.push_back(*it);
  }

  double min[3],max[3],x,y,z,h;
  for(unsigned int i=0;i<boundary_vertices.size();i++){

    x = boundary_vertices[i]->x();
    y = boundary_vertices[i]->y();
    z = boundary_vertices[i]->z();

    // "on boundary since working on boundary_vertices ...
    MVertex *closest = bgm->get_nearest_neighbor_on_boundary(boundary_vertices[i]);
    h = bgm->size(closest);// get approximate size, closest vertex, faster ?!

    fill_min_max(x,y,z,h,min,max);

    rtree.Insert(min,max,boundary_vertices[i]);

    if (!use_vectorial_smoothness){
      smoothness_vertex_pair *svp = new smoothness_vertex_pair();
      svp->v = boundary_vertices[i];
      svp->rank = bgm->get_smoothness(x,y,z);
      svp->dir = 0;
      svp->layer = 0;
      svp->size = h;
      bgm->eval_approximate_crossfield(closest, svp->cf);

      fifo->insert(svp);
      if (debug){
        smoothness_forplot[svp->v] = svp->rank;
      }
    }
    else{
      STensor3 temp;
      bgm->eval_approximate_crossfield(closest, temp);
      for (int idir=0;idir<3;idir++){
        smoothness_vertex_pair *svp = new smoothness_vertex_pair();
        svp->v = boundary_vertices[i];
        svp->rank = bgm->get_vectorial_smoothness(idir,x,y,z);
        svp->dir = idir;
        svp->layer = 0;
        svp->size = h;
        svp->cf = temp;
        for (int k=0;k<3;k++) svp->direction(k) = temp(k,idir);

        // cout << "fifo size=" << fifo->size() << " inserting   "  ;
        fifo->insert(svp);
        // cout << " ->  fifo size=" << fifo->size() << endl;
      }
    }
  }

  // TODO: si fifo était list of *PTR -> pas de copies, gain temps ?
  Wrapper3D wrapper;
  wrapper.set_bgm(bgm);
  MVertex *parent,*individual;
  new_vertices.clear();
  bool spawn_created;
  int priority_counter=0;
  STensor3 crossfield;
  int parent_layer;

  while(!fifo->empty()){

    parent =  fifo->get_first_vertex();
    //    parent_limit = fifo->get_first_limit();
    parent_layer = fifo->get_first_layer();

    //    if(parent_limit!=-1 && parent_layer>=parent_limit()){
    //      continue;
    //    }

    vector<MVertex*> spawns;
    if (!use_vectorial_smoothness){
      spawns.resize(6);
      computeSixNeighbors(bgm,parent,spawns,fifo->get_first_crossfield(),
                          fifo->get_first_size());
    }
    else{
      spawns.resize(2);
      computeTwoNeighbors(bgm,parent,spawns,fifo->get_first_direction(),
                          fifo->get_first_size());
    }
    fifo->erase_first();

    //    cout << "while, fifo->size()=" << fifo->size() << " parent=(" <<
    //    parent->x() << "," << parent->y() << "," << parent->z() << ")" <<
    //    endl;

    for(unsigned int i=0;i<spawns.size();i++){
      spawn_created = false;
      individual = spawns[i];
      x = individual->x();
      y = individual->y();
      z = individual->z();
      //      cout << " working on candidate " << "(" << individual->x() << ","
      //      << individual->y() << "," << individual->z() << ")" << endl;

      if(bgm->inDomain(x,y,z)){
        //        cout << "   spawn " << i << " in domain" << endl;

        MVertex *closest = bgm->get_nearest_neighbor(individual);
        h = bgm->size(closest);// get approximate size, closest vertex, faster ?!

        if(far_from_boundary_3D(bgm,individual,h)){
          //        cout << "   spawn " << i << " far from bnd" << endl;
          bgm->eval_approximate_crossfield(closest, crossfield);
          wrapper.set_ok(true);
          wrapper.set_individual(individual);
          wrapper.set_parent(parent);
          wrapper.set_size(&h);
          wrapper.set_crossfield(&crossfield);

          fill_min_max(x,y,z,h,min,max);

          rtree.Search(min,max,rtree_callback_3D,&wrapper);

          if(wrapper.get_ok()){
            //        cout << "   spawn " << i << " wrapper OK" << endl;

            if (!use_vectorial_smoothness){
              smoothness_vertex_pair *svp = new smoothness_vertex_pair();
              svp->v = individual;
              svp->rank=bgm->get_smoothness(individual->x(),individual->y(),individual->z());
              svp->dir = 0;
              svp->layer = parent_layer+1;
              svp->size = h;
              svp->cf = crossfield;
              fifo->insert(svp);
              if (debug){
                smoothness_forplot[svp->v] = svp->rank;
                vert_priority[individual] = priority_counter++;
              }

            }
            else{
              if (debug) vert_priority[individual] = priority_counter++;
              for (int idir=0;idir<3;idir++){
                smoothness_vertex_pair *svp = new smoothness_vertex_pair();
                svp->v = individual;
                svp->rank = bgm->get_vectorial_smoothness(idir,x,y,z);
                svp->dir = idir;
                svp->layer = parent_layer+1;
                svp->size = h;
                for (int k=0;k<3;k++) svp->direction(k) = crossfield(k,idir);
                svp->cf = crossfield;
                fifo->insert(svp);
              }
            }

            rtree.Insert(min,max,individual);
            new_vertices.push_back(individual);
            spawn_created = true;

          }
        }
      }
      if(!spawn_created){
        delete individual;
      }
    }// end loop on spawns
  }

  //ProfilerStop();

  time_insert_points += (Cpu() - a);

  // --- output ---
  if (debug){
    stringstream ss;
    ss << "priority_3D_" << gr->tag() << ".pos";
    print_nodal_info(ss.str().c_str(),vert_priority);
    ss.clear();

    stringstream sss;
    sss << "smoothness_3D_" << gr->tag() << ".pos";
    print_nodal_info(sss.str().c_str(),smoothness_forplot);
    sss.clear();
  }

  // ------- meshing using new points
  cout << "tets in gr before= " << gr->tetrahedra.size() << endl;
  cout << "nb new vertices= " << new_vertices.size() << endl;
  a=Cpu();

  int option = CTX::instance()->mesh.algo3d;
  CTX::instance()->mesh.algo3d = ALGO_3D_DELAUNAY;

  deMeshGRegion deleter;
  deleter(gr);
  std::vector<GRegion*> regions;
  regions.push_back(gr);
  meshGRegion mesher(regions); //?
  mesher(gr); //?
  MeshDelaunayVolume(regions);
  time_meshing += (Cpu() - a);

  cout << "tets in gr after= " << gr->tetrahedra.size() << endl;
  cout << "gr tag=" << gr->tag() << endl;

  CTX::instance()->mesh.algo3d = option;

  delete fifo;
  for(unsigned int i=0;i<new_vertices.size();i++) delete new_vertices[i];
  new_vertices.clear();
  rtree.RemoveAll();

  return true;
}
Example #19
0
int GModel::writeCELUM(const std::string &name, bool saveAll,
                       double scalingFactor)
{
  std::string namef = name + "_f";
  FILE *fpf = Fopen(namef.c_str(), "w");
  if(!fpf) {
    Msg::Error("Unable to open file '%s'", namef.c_str());
    return 0;
  }

  std::string names = name + "_s";
  FILE *fps = Fopen(names.c_str(), "w");
  if(!fps) {
    Msg::Error("Unable to open file '%s'", names.c_str());
    fclose(fpf);
    return 0;
  }

  if(noPhysicalGroups()) saveAll = true;

  // count faces and vertices; the CELUM format duplicates vertices on the
  // boundary of CAD patches
  int numf = 0, nums = 0;
  for(fiter it = firstFace(); it != lastFace(); it++) {
    GFace *f = *it;
    if(!saveAll && f->physicals.empty()) continue;
    numf += f->triangles.size();
    std::set<MVertex *> vset;
    for(std::size_t i = 0; i < f->triangles.size(); i++) {
      for(int j = 0; j < 3; j++) vset.insert(f->triangles[i]->getVertex(j));
    }
    nums += vset.size();
  }

  Msg::Info("Writing %d triangles and %d vertices", numf, nums);

  int idf = 1, ids = 1;
  /*
   * a file with faces
     - number of faces
     - empty line
     ... for each face
     - number of the face (starts at 1 : used for read errors)
     - char string (name of geom part, material,... )
     - list of 3 vertex nums
     - empty line
     ...
   * a file with vertices
     - number of vertices
     - conversion factor
     - empty line
     ... for each vertex
     - number of the vertex (starts at 1 : used for read errors)
     - cartesian coordinates of the vertex
     - componants of the exterior oriented normal
     - value of 1st principal curvature
     - value of second princpal curvature
     - components of 1st principal direction
     - components of 2nd principal direction
     - empty line
     ...
  */
  fprintf(fpf, "%d\n\n", numf);
  fprintf(fps, "%d %g\n\n", nums, 1.0);
  for(fiter it = firstFace(); it != lastFace(); it++) {
    GFace *f = *it;
    if(!saveAll && f->physicals.empty()) continue;
    std::vector<MVertex *> vvec;
    std::map<MVertex *, CelumInfo> vmap;
    for(std::size_t i = 0; i < f->triangles.size(); i++) {
      fprintf(fpf, "%d \"face %d\"", idf++, f->tag());
      for(int j = 0; j < 3; j++) {
        MVertex *v = f->triangles[i]->getVertex(j);
        if(!vmap.count(v)) {
          v->setIndex(ids++);
          SPoint2 param;
          bool ok = reparamMeshVertexOnFace(v, f, param);
          if(!ok)
            Msg::Warning("Could not reparamtrize vertex %d on face %d",
                         v->getNum(), f->tag());
          CelumInfo info;
          info.normal = f->normal(param);
          f->curvatures(param, info.dirMax, info.dirMin, info.curvMax,
                        info.curvMin);
          vmap[v] = info;
          vvec.push_back(v);
        }
        fprintf(fpf, " %ld", v->getIndex());
      }
      fprintf(fpf, "\n\n");
    }
    for(std::size_t i = 0; i < vvec.size(); i++) {
      MVertex *v = vvec[i];
      std::map<MVertex *, CelumInfo>::iterator it = vmap.find(v);
      fprintf(fps, "%ld %g %g %g %g %g %g %g %g %g %g %g %g %g %g\n\n",
              it->first->getIndex(), it->first->x(), it->first->y(),
              it->first->z(), it->second.normal.x(), it->second.normal.y(),
              it->second.normal.z(), it->second.curvMin, it->second.curvMax,
              it->second.dirMin.x(), it->second.dirMin.y(),
              it->second.dirMin.z(), it->second.dirMax.x(),
              it->second.dirMax.y(), it->second.dirMax.z());
    }
  }

  fclose(fpf);
  fclose(fps);
  return 1;
}
Example #20
0
bool frameFieldBackgroundMesh2D::compute_RK_infos(double u,double v, double x, double y, double z, RK_form &infos)
{
    // check if point is in domain
    if (!inDomain(u,v)) return false;

    // get stored angle

    double angle_current = angle(u,v);

    // compute t1,t2: cross field directions

    // get the unit normal at that point
    GFace *face = dynamic_cast<GFace*>(gf);
    if(!face) {
        Msg::Error("Entity is not a face in background mesh");
        return false;
    }

    Pair<SVector3, SVector3> der = face->firstDer(SPoint2(u,v));
    SVector3 s1 = der.first();
    SVector3 s2 = der.second();
    SVector3 n = crossprod(s1,s2);
    n.normalize();
    SVector3 basis_u = s1;
    basis_u.normalize();
    SVector3 basis_v = crossprod(n,basis_u);
    // normalize vector t1 that is tangent to gf at uv
    SVector3 t1 = basis_u * cos(angle_current) + basis_v * sin(angle_current) ;
    t1.normalize();
    // compute the second direction t2 and normalize (t1,t2,n) is the tangent frame
    SVector3 t2 = crossprod(n,t1);
    t2.normalize();

    // get metric

    double L = size(u,v);
    infos.metricField = SMetric3(1./(L*L));
    FieldManager *fields = gf->model()->getFields();
    if(fields->getBackgroundField() > 0) {
        Field *f = fields->get(fields->getBackgroundField());
        if (!f->isotropic()) {
            (*f)(x,y,z, infos.metricField,gf);
        }
        else {
            L = (*f)(x,y,z,gf);
            infos.metricField = SMetric3(1./(L*L));
        }
    }
    double M = dot(s1,s1);
    double N = dot(s2,s2);
    double E = dot(s1,s2);
    // compute the first fundamental form i.e. the metric tensor at the point
    // M_{ij} = s_i \cdot s_j
    double metric[2][2] = {{M,E},{E,N}};

    // get sizes

    double size_1 = sqrt(1. / dot(t1,infos.metricField,t1));
    double size_2 = sqrt(1. / dot(t2,infos.metricField,t2));

    // compute covariant coordinates of t1 and t2 - cross field directions in parametric domain
    double covar1[2],covar2[2];
    // t1 = a s1 + b s2 -->
    // t1 . s1 = a M + b E
    // t1 . s2 = a E + b N --> solve the 2 x 2 system
    // and get covariant coordinates a and b
    double rhs1[2] = {dot(t1,s1),dot(t1,s2)};
    bool singular = false;
    if (!sys2x2(metric,rhs1,covar1)) {
        Msg::Info("Argh surface %d %g %g %g -- %g %g %g -- %g %g",gf->tag(),s1.x(),s1.y(),s1.z(),s2.x(),s2.y(),s2.z(),size_1,size_2);
        covar1[1] = 1.0;
        covar1[0] = 0.0;
        singular = true;
    }
    double rhs2[2] = {dot(t2,s1),dot(t2,s2)};
    if (!sys2x2(metric,rhs2,covar2)) {
        Msg::Info("Argh surface %d %g %g %g -- %g %g %g",gf->tag(),s1.x(),s1.y(),s1.z(),s2.x(),s2.y(),s2.z());
        covar2[0] = 1.0;
        covar2[1] = 0.0;
        singular = true;
    }

    // transform the sizes with respect to the metric
    // consider a vector v of size 1 in the parameter plane
    // its length is sqrt (v^T M v) --> if I want a real size
    // of size1 in direction v, it should be sqrt(v^T M v) * size1
    double l1 = sqrt(covar1[0]*covar1[0]+covar1[1]*covar1[1]);
    double l2 = sqrt(covar2[0]*covar2[0]+covar2[1]*covar2[1]);

    covar1[0] /= l1;
    covar1[1] /= l1;
    covar2[0] /= l2;
    covar2[1] /= l2;

    double size_param_1  = size_1 / sqrt (  M*covar1[0]*covar1[0]+
                                            2*E*covar1[1]*covar1[0]+
                                            N*covar1[1]*covar1[1]);
    double size_param_2  = size_2 / sqrt (  M*covar2[0]*covar2[0]+
                                            2*E*covar2[1]*covar2[0]+
                                            N*covar2[1]*covar2[1]);
    if (singular) {
        size_param_1 = size_param_2 = std::min (size_param_1,size_param_2);
    }


    // filling form...

    infos.t1 = t1;
    infos.h.first  = size_1;
    infos.h.second = size_2;
    infos.paramh.first  = size_param_1;
    infos.paramh.second = size_param_2;
    infos.paramt1 = SPoint2(covar1[0],covar1[1]);
    infos.paramt2 = SPoint2(covar2[0],covar2[1]);
    infos.angle = angle_current;
    infos.localsize = L;
    infos.normal = n;

    return true;
}
Example #21
0
void Centerline::extrudeBoundaryLayerWall(GEdge* gin, std::vector<GEdge*> boundEdges)
{
  Msg::Info("Centerline: extrude boundary layer wall (%d, %g%%R) ", nbElemLayer,  hLayer);

  //orient extrude direction outward
  int dir = 0;
  MElement *e = current->getFaceByTag(1)->getMeshElement(0);
  SVector3 ne = e->getFace(0).normal();
  SVector3 ps(e->getVertex(0)->x(), e->getVertex(0)->y(), e->getVertex(0)->z());
  double xyz[3] = {ps.x(), ps.y(), ps.z()};
  ANNidx index[1];
  ANNdist dist[1];
  kdtree->annkSearch(xyz, 1, index, dist);
  ANNpointArray nodes = kdtree->thePoints();
  SVector3 pc(nodes[index[0]][0], nodes[index[0]][1], nodes[index[0]][2]);
  SVector3 nc = ps-pc;
  if (dot(ne,nc) < 0) dir = 1;
  if (dir == 1 && hLayer > 0 ) hLayer *= -1.0;

  //int shift = 0;
  //if(is_cut) shift = NE;
  for (int i= 0; i< NF; i++){
    GFace *gfc ;
    if (is_cut) gfc = current->getFaceByTag(NF+i+1);
    else gfc = current->getFaceByTag(i+1);
    current->setFactory("Gmsh");
    //view -5 to scale hLayer by radius in BoundaryLayers.cpp
    std::vector<GEntity*> extrudedE = current->extrudeBoundaryLayer
      (gfc, nbElemLayer,  hLayer, dir, -5);
    GFace *eFace = (GFace*) extrudedE[0];
    eFace->addPhysicalEntity(5);
    current->setPhysicalName("outerWall", 2, 5);//dim 2 tag 5
    GRegion *eRegion = (GRegion*) extrudedE[1];
    eRegion->addPhysicalEntity(6);
    current->setPhysicalName("wallVolume", 3, 6);//dim 3 tag 6

    //if double extruded layer
    if (nbElemSecondLayer > 0){
      std::vector<GEntity*> extrudedESec = current->extrudeBoundaryLayer
      	(eFace, nbElemSecondLayer,  hSecondLayer, dir, -5);
      GFace *eFaceSec = (GFace*) extrudedESec[0];
      eFaceSec->addPhysicalEntity(9);                    //tag 9
      current->setPhysicalName("outerSecondWall", 2, 9);//dim 2 tag 9
      GRegion *eRegionSec = (GRegion*) extrudedESec[1];
      eRegionSec->addPhysicalEntity(10);             //tag 10
      current->setPhysicalName("wallVolume", 3, 10);//dim 3 tag 10
    }
    //end double extrusion

    for (unsigned int j = 2; j < extrudedE.size(); j++){
      GFace *elFace = (GFace*) extrudedE[j];
      std::list<GEdge*> l_edges = elFace->edges();
      for(std::list<GEdge*>::iterator it = l_edges.begin(); it != l_edges.end(); it++){
	GEdge *myEdge = *it;
	if (is_cut) myEdge = current->getEdgeByTag((*it)->tag()-NE);
	if( std::find(boundEdges.begin(), boundEdges.end(), myEdge) != boundEdges.end() ){
	  if (myEdge==gin){
	    elFace->addPhysicalEntity(7);
	    current->setPhysicalName("inletRing", 2, 7);//tag 7
	  }
	  else{
	    elFace->addPhysicalEntity(8);
	    current->setPhysicalName("outletRings", 2, 8);//tag 8
	  }
	}
      }
    }
  }

}
Example #22
0
int SubdivideExtrudedMesh(GModel *m)
{
  // get all non-recombined extruded regions and vertices; also,
  // create a vector of quadToTri regions that have NOT been meshed
  // yet
  std::vector<GRegion*> regions, regions_quadToTri;
  MVertexRTree pos(CTX::instance()->geom.tolerance * CTX::instance()->lc);
  for(GModel::riter it = m->firstRegion(); it != m->lastRegion(); it++){
    ExtrudeParams *ep = (*it)->meshAttributes.extrude;
    if(ep && ep->mesh.ExtrudeMesh && ep->geo.Mode == EXTRUDED_ENTITY &&
       !ep->mesh.Recombine){
      regions.push_back(*it);
      insertAllVertices(*it, pos);
    }
    // create vector of valid quadToTri regions...not all will necessarily be meshed here.
    if(ep && ep->mesh.ExtrudeMesh && ep->geo.Mode == EXTRUDED_ENTITY &&
       ep->mesh.Recombine && ep->mesh.QuadToTri){
      regions_quadToTri.push_back(*it);
    }
  }

  if(regions.empty()) return 0;
  Msg::Info("Subdividing extruded mesh");

  // create edges on lateral sides of "prisms"
  std::set<std::pair<MVertex*, MVertex*> > edges;
  for(unsigned int i = 0; i < regions.size(); i++)
    phase1(regions[i], pos, edges);

  // swap lateral edges to make them "tet-compatible"
  int j = 0, swap;
  std::set<std::pair<MVertex*, MVertex*> > edges_swap;
  do {
    swap = 0;
    for(unsigned int i = 0; i < regions.size(); i++)
      phase2(regions[i], pos, edges, edges_swap, swap);
    Msg::Info("Swapping %d", swap);
    if(j && j == swap) {
      Msg::Error("Unable to subdivide extruded mesh: change surface mesh or");
      Msg::Error("recombine extrusion instead");
      return -1;
    }
    j = swap;
  } while(swap);

  // delete volume elements and create tetrahedra instead
  for(unsigned int i = 0; i < regions.size(); i++){
    GRegion *gr = regions[i];

    for(unsigned int i = 0; i < gr->tetrahedra.size(); i++)
      delete gr->tetrahedra[i];
    gr->tetrahedra.clear();
    for(unsigned int i = 0; i < gr->hexahedra.size(); i++)
      delete gr->hexahedra[i];
    gr->hexahedra.clear();
    for(unsigned int i = 0; i < gr->prisms.size(); i++)
      delete gr->prisms[i];
    gr->prisms.clear();
    for(unsigned int i = 0; i < gr->pyramids.size(); i++)
      delete gr->pyramids[i];
    gr->pyramids.clear();
    phase3(gr, pos, edges);

    // re-Extrude bounding surfaces using edges as constraint
    std::list<GFace*> faces = gr->faces();
    for(std::list<GFace*>::iterator it = faces.begin(); it != faces.end(); it++){
      ExtrudeParams *ep = (*it)->meshAttributes.extrude;
      if(ep && ep->mesh.ExtrudeMesh && ep->geo.Mode == EXTRUDED_ENTITY &&
        !ep->mesh.Recombine){
        GFace *gf = *it;
        Msg::Info("Remeshing surface %d", gf->tag());
        for(unsigned int i = 0; i < gf->triangles.size(); i++)
          delete gf->triangles[i];
        gf->triangles.clear();
        for(unsigned int i = 0; i < gf->quadrangles.size(); i++)
          delete gf->quadrangles[i];
        gf->quadrangles.clear();
        MeshExtrudedSurface(gf, &edges);
      }
    }
  }

  // now mesh the QuadToTri regions. Everything can be done locally
  // for each quadToTri region, but still use edge set from above just
  // to make sure laterals get remeshed properly (
  // QuadToTriEdgeGenerator detects if the neighbor has been meshed or
  // if a lateral surface should remain static for any other reason).
  // If this function detects allNonGlobalSharedLaterals, it won't
  // mesh the region (should already be done in ExtrudeMesh).
  for(unsigned int i = 0; i < regions_quadToTri.size(); i++){
    GRegion *gr = regions_quadToTri[i];
    MVertexRTree pos_local(CTX::instance()->geom.tolerance * CTX::instance()->lc);
    insertAllVertices(gr, pos_local);
    meshQuadToTriRegionAfterGlobalSubdivide(gr, &edges, pos_local);
  }

  // carve holes if any
  // TODO: update extrusion information
  for(unsigned int i = 0; i < regions.size(); i++){
    GRegion *gr = regions[i];
    ExtrudeParams *ep = gr->meshAttributes.extrude;
    if(ep->mesh.Holes.size()){
      std::map<int, std::pair<double, std::vector<int> > >::iterator it;
      for(it = ep->mesh.Holes.begin(); it != ep->mesh.Holes.end(); it++)
        carveHole(gr, it->first, it->second.first, it->second.second);
    }
  }
  for(unsigned int i = 0; i < regions_quadToTri.size(); i++){
    GRegion *gr = regions_quadToTri[i];
    ExtrudeParams *ep = gr->meshAttributes.extrude;
    if(ep->mesh.Holes.size()){
      std::map<int, std::pair<double, std::vector<int> > >::iterator it;
      for(it = ep->mesh.Holes.begin(); it != ep->mesh.Holes.end(); it++)
        carveHole(gr, it->first, it->second.first, it->second.second);
    }
  }

  return 1;
}