diff --git a/Geo/boundaryLayersData.cpp b/Geo/boundaryLayersData.cpp index 32d5403ac6246dd824dfe346ce8475fad0bc771a..494383ed2d6dbe6a140bdbd00c9d7c02b8eab5ea 100644 --- a/Geo/boundaryLayersData.cpp +++ b/Geo/boundaryLayersData.cpp @@ -3,32 +3,26 @@ // See the LICENSE.txt file for license information. Please report all // bugs and problems to the public mailing list <gmsh@onelab.info>. -#include <stack> +#include "boundaryLayersData.h" #include "GmshConfig.h" #include "GModel.h" -#include "GFace.h" -#include "MVertex.h" #include "MLine.h" #include "MTriangle.h" -#include "MTetrahedron.h" -#include "MHexahedron.h" -#include "MPrism.h" #include "MEdge.h" -#include "boundaryLayersData.h" #include "OS.h" -#include "BackgroundMesh.h" #if !defined(HAVE_MESH) || !defined(HAVE_ANN) BoundaryLayerField* getBLField(GModel *gm){ return 0; } bool buildAdditionalPoints2D (GFace *gf ) { return false; } bool buildAdditionalPoints3D (GRegion *gr) { return false; } -void buildMeshMetric(GFace *gf, double *uv, SMetric3 &m, double metric[3]) {} -faceColumn BoundaryLayerColumns::getColumns(GFace *gf, MVertex *v1, MVertex *v2, +//void buildMeshMetric(GFace *gf, double *uv, SMetric3 &m, double metric[3]) {} +/*faceColumn BoundaryLayerColumns::getColumns(GFace *gf, MVertex *v1, MVertex *v2, MVertex *v3, int side) { return faceColumn(BoundaryLayerData(),BoundaryLayerData(),BoundaryLayerData()); } +*/ edgeColumn BoundaryLayerColumns::getColumns(MVertex *v1, MVertex *v2 , int side) { return edgeColumn(BoundaryLayerData(),BoundaryLayerData()); @@ -54,18 +48,6 @@ const int FANSIZE__ = 4; + */ -/* -static double solidAngle (SVector3 &ni, SVector3 &nj, - SPoint3 &bi, SPoint3 &bj) -{ - double cosa = dot (ni, nj); - SVector3 bibj = bj - bi; - SVector3 sina = crossprod ( ni , nj ); - double a = atan2(sina.norm(),cosa); - double sign = dot (nj, bibj); - return sign > 0 ? fabs (a) : -fabs(a); -} -*/ SVector3 interiorNormal(SPoint2 p1, SPoint2 p2, SPoint2 p3) { @@ -78,124 +60,6 @@ SVector3 interiorNormal(SPoint2 p1, SPoint2 p2, SPoint2 p3) return n*(-1.); } -double computeAngle(GFace *gf, const MEdge &e1, const MEdge &e2, - SVector3 &n1, SVector3 &n2) -{ - double cosa = dot(n1,n2); - SPoint2 p0,p1,p2; - MVertex *v11 = e1.getVertex(0); - MVertex *v12 = e1.getVertex(1); - MVertex *v21 = e2.getVertex(0); - MVertex *v22 = e2.getVertex(1); - MVertex *v0,*v1,*v2; - if (v11 == v21){ - v0 = v12 ; v1 = v11 ; v2 = v22; - } - else if (v11 == v22){ - v0 = v12 ; v1 = v11 ; v2 = v21; - } - else if (v12 == v21){ - v0 = v11 ; v1 = v12 ; v2 = v22; - } - else if (v12 == v22){ - v0 = v11 ; v1 = v12 ; v2 = v21; - } - else throw; - - reparamMeshEdgeOnFace(v0, v1, gf, p0, p1); - reparamMeshEdgeOnFace(v0, v2, gf, p0, p2); - - SVector3 t1 (p1.x()-p0.x(),p1.y()-p0.y(),0); - SVector3 t2 (p2.x()-p1.x(),p2.y()-p1.y(),0); - t1.normalize(); - t2.normalize(); - SVector3 n = crossprod(t1,t2); - - double sign = dot(t1,n2); - - double a = atan2 (n.z(),cosa); - a = sign > 0 ? fabs(a) : -fabs(a); - - // printf("a = %12.5e cos %12.5E sin %12.5E %g %g vs %g %g\n", - // a,cosa,n.z(),n1.x(),n1.y(),n2.x(),n2.y()); - return a; -} - -void buildMeshMetric(GFace *gf, double *uv, SMetric3 &m, double metric[3]) -{ - Pair<SVector3, SVector3> der = gf->firstDer(SPoint2(uv[0], uv[1])); - - double res[2][2]; - - double M[2][3] = {{der.first().x(),der.first().y(),der.first().z()}, - {der.second().x(),der.second().y(),der.second().z()}}; - - - for (int i=0;i<2;i++){ - for (int l=0;l<2;l++){ - res[i][l] = 0; - for (int j=0;j<3;j++){ - for (int k=0;k<3;k++){ - res[i][l] += M[i][j]*m(j,k)*M[l][k]; - } - } - } - } - metric[0] = res[0][0]; - metric[1] = res[1][0]; - metric[2] = res[1][1]; -} - -const BoundaryLayerData & BoundaryLayerColumns::getColumn(MVertex *v, MFace f) const -{ - int N = getNbColumns(v) ; - if (N == 1) return getColumn(v, 0); - std::map<MFace, GFace*, Less_Face>::const_iterator it = _inverse_classification.find(f); - if (it != _inverse_classification.end()) { - GFace *gf = it->second; - for (int i=0;i<N;i++){ - const BoundaryLayerData & c = getColumn(v, i); - if (std::find(c._joint.begin(),c._joint.end(),gf) != c._joint.end())return c; - } - } - static BoundaryLayerData error; - return error; -} - - -faceColumn BoundaryLayerColumns::getColumns(GFace *gf, MVertex *v1, MVertex *v2, - MVertex *v3, int side) -{ - // printf("%d %d %d for vertex face %d\n",getNbColumns(v1),getNbColumns(v3),getNbColumns(v3), - // gf->tag()); - int i1=-1,i2=-1,i3=-1; - for (int i=0;i<getNbColumns(v1);i++){ - const BoundaryLayerData &d1 = getColumn(v1,i); - if (std::find(d1._joint.begin(),d1._joint.end(),gf) != d1._joint.end()){ - i1 = i; - // printf("1 Yeah column %d among %d\n",i,d1._joint.size()); - break; - } - } - for (int i=0;i<getNbColumns(v2);i++){ - const BoundaryLayerData &d2 = getColumn(v2,i); - if (std::find(d2._joint.begin(),d2._joint.end(),gf) != d2._joint.end()){ - i2 = i; - // printf("2 Yeah column %d among %d\n",i,d2._joint.size()); - break; - } - } - for (int i=0;i<getNbColumns(v3);i++){ - const BoundaryLayerData &d3 = getColumn(v3,i); - if (std::find(d3._joint.begin(),d3._joint.end(),gf) != d3._joint.end()){ - i3 = i; - // printf("3 Yeah column %d among %d\n",i,d3._joint.size()); - break; - } - } - - return faceColumn(getColumn(v1,i1), getColumn(v2,i2), getColumn(v3,i3)); -} edgeColumn BoundaryLayerColumns::getColumns(MVertex *v1, MVertex *v2 , int side) { @@ -312,8 +176,6 @@ static void treat2Connections(GFace *gf, MVertex *_myVert, MEdge &e1, MEdge &e2, itm != _columns->_normals.upper_bound(e2); ++itm) N2.push_back(itm->second); if (N1.size() == N2.size()){ for (unsigned int SIDE = 0; SIDE < N1.size() ; SIDE++){ - // IF THE ANGLE IS GREATER THAN THRESHOLD, ADD DIRECTIONS !! - // double angle = computeAngle (gf,e1,e2,N1[SIDE],N2[SIDE]); if (!fan){ SVector3 x = N1[SIDE]*1.01+N2[SIDE]; x.normalize(); @@ -321,7 +183,7 @@ static void treat2Connections(GFace *gf, MVertex *_myVert, MEdge &e1, MEdge &e2, } else if (fan){ - printf("fan \n"); + // printf("fan \n"); int fanSize = FANSIZE__; // if the angle is greater than PI, than reverse the sense @@ -526,31 +388,27 @@ static void addColumnAtTheEndOfTheBL(GEdge *ge, MVertex * v0 = g0->mesh_vertices[0]; MVertex * v1 = g1->mesh_vertices[0]; std::vector<MVertex*> invert; - std::vector<SMetric3> _metrics; + // std::vector<SMetric3> _metrics; for(unsigned int i = 0; i < ge->mesh_vertices.size() ; i++){ invert.push_back(ge->mesh_vertices[ge->mesh_vertices.size() - i - 1]); - _metrics.push_back(SMetric3(1.0)); + // _metrics.push_back(SMetric3(1.0)); } SVector3 t (v1->x()-v0->x(), v1->y()-v0->y(),v1->z()-v0->z()); t.normalize(); if (g0 == gv){ - _columns->addColumn(t, v0, ge->mesh_vertices,_metrics); + _columns->addColumn(t, v0, ge->mesh_vertices/*,_metrics*/); } else if (g1 == gv){ - _columns->addColumn(t*-1.0, v1,invert,_metrics); + _columns->addColumn(t*-1.0, v1,invert/*,_metrics*/); } } } bool buildAdditionalPoints2D(GFace *gf) { - // printf("coucou1\n"); - + BoundaryLayerColumns *_columns = gf->getColumns(); - - _columns->_normals.clear(); - _columns->_non_manifold_edges.clear(); - _columns->_data.clear(); + _columns->clearData(); // GET THE FIELD THAT DEFINES THE DISTANCE FUNCTION BoundaryLayerField *blf = getBLField (gf->model()); @@ -673,7 +531,6 @@ bool buildAdditionalPoints2D(GFace *gf) // now create the BL points for (unsigned int DIR=0;DIR<_dirs.size();DIR++){ - SPoint2 p; SVector3 n = _dirs[DIR]; // < ------------------------------- > // @@ -690,51 +547,23 @@ bool buildAdditionalPoints2D(GFace *gf) // printf( "coucou c'est moi\n"); } else { - MVertex *current = *it; - reparamMeshVertexOnFace(current,gf,p); - - int nbCol = 100; + MVertex *first = *it; std::vector<MVertex*> _column; - std::vector<SMetric3> _metrics; - // printf("start with point %g %g (%g %g)\n",current->x(),current->y(),p.x(),p.y()); - AttractorField *catt = 0; - SPoint3 _close; - //double _current_distance = 0.; + SPoint2 par = gf->parFromPoint(SPoint3(first->x(),first->y(),first->z())); + double L = blf->hwall_n ; while(1){ - - SMetric3 m; - double metric[3]; - double l; - (*blf)(current->x(),current->y(), current->z(), m, current->onWhat()); - if (!catt){ - catt = blf->current_closest; - _close = blf->_closest_point; - //_current_distance = blf -> current_distance; - } - SPoint2 poffset (p.x() + 1.e-12 * n.x(), - p.y() + 1.e-12 * n.y()); - buildMeshMetric(gf, poffset, m, metric); - const double l2 = n.x()*n.x()*metric[0] + 2*n.x()*n.y()*metric[1] + n.y()*n.y()*metric[2] ; - l = 1./sqrt(l2); - if (l >= blf->hfar){ - break; - } - if (blf -> current_distance > blf->thickness) break; - catt = blf->current_closest; - _close = blf->_closest_point; - //_current_distance = blf -> current_distance; - SPoint2 pnew (p.x() + l * n.x(), - p.y() + l * n.y()); - GPoint gp = gf->point (pnew); - MFaceVertex *_current = new MFaceVertex (gp.x(),gp.y(),gp.z(),gf,pnew.x(),pnew.y()); + // printf("L = %g\n",L); + if (L > blf->thickness) break; + SPoint2 pnew (par.x() + L * n.x(), + par.y() + L * n.y()); + GPoint pp = gf->point(pnew); + MFaceVertex *_current = new MFaceVertex (pp.x(),pp.y(),pp.z(),gf,pnew.x(),pnew.y()); _current->bl_data = new MVertexBoundaryLayerData; - current = _current; - _column.push_back(current); - _metrics.push_back(m); - if ((int)_column.size() > nbCol) break; // FIXME - p = pnew; + _column.push_back(_current); + int ith = _column.size() ; + L+= blf->hwall_n * pow (blf->ratio, ith); } - _columns->addColumn(n,*it, _column, _metrics); + _columns->addColumn(n,*it, _column /*,_metrics*/); } } } @@ -763,594 +592,7 @@ bool buildAdditionalPoints2D(GFace *gf) return 1; } -static double angle_0_180(SVector3 &n1, SVector3 &n2) -{ - double cosa = dot(n1,n2)/(n1.norm()*n2.norm()); - if (cosa > 1.) cosa = 1.0; - if (cosa < -1.) cosa = -1.0; - return acos(cosa); -} - -static void createBLPointsInDir(GRegion *gr, - MVertex *current, - BoundaryLayerField *blf, - SVector3 & n, - std::vector<MVertex*> &_column, - std::vector<SMetric3> &_metrics) -{ - SVector3 basis (current->x(),current->y(),current->z()); - double H = blf->hwall_n; - double dist = H; - while(dist < blf->thickness){ - SVector3 newp = basis + n * H; - MVertex *_current = new MVertex (newp.x(),newp.y(),newp.z(),gr); - // gr->mesh_vertices.push_back(_current); - _column.push_back(_current); - H *= blf->ratio; - dist += H; - basis = newp; - } -} - - -static bool createWedgeBetweenTwoFaces(MVertex *myV, - SVector3 n1, SVector3 n2, - std::vector<SVector3> &shoot) -{ - double angle = angle_0_180 (n1,n2); - int fanSize = FANSIZE__; - for (int i=-1; i<=fanSize; i++){ - - double ti = (double)(i+1)/ (fanSize+1); - double angle_t = ti * angle; - double cosA = cos (angle_t); - double cosAlpha = dot(n1,n2); - - const double A = (1.- 2.*cosA*cosA) + cosAlpha*cosAlpha - 2 * cosAlpha*(1.-cosA*cosA); - const double B = -2*(1.-cosA*cosA)*(1-cosAlpha); - const double C = 1.-cosA*cosA; - double DELTA = B*B-4*A*C; - double t = 0.0; - if (A == 0.0){ - t = -C / B; - } - else if (C != 0.0){ - if (DELTA < 0){ - Msg::Error("this should not happen DELTA = %12.5E",DELTA); - DELTA = 0; - } - const double t1 = (-B+sqrt(DELTA))/(2.*A); - const double t2 = (-B-sqrt(DELTA))/(2.*A); - - SVector3 x1 (n1*(1.-t1) + n2 * t2); - SVector3 x2 (n1*(1.-t2) + n2 * t2); - double a1 = angle_0_180 (n1,x1); - double a2 = angle_0_180 (n1,x2); - if (fabs(a1 - angle_t) < fabs(a2 - angle_t))t = t1; - else t = t2; - } - SVector3 x (n1*(1.-t) + n2 * t); - x.normalize(); - shoot.push_back(x); - } - return true; -} - - - -/* - a "fanned" edge is one that opens a fan of element between the 2 faces - it connects in the volume. - - fan start (end) - --> at a symmetry plane or at an inflow/outflow bdry. This implies - that the fan has a trace on this boundary - --> at a corner where at least 3 incident model edges are "fanned" - - fan can also be doing a closed loop - - when looking at a model vertex, one can then have - --> At least 3 fanned edges : this is a corner - --> Two fanned edges : this is the passage of a fan - --> A model vertex that has one single incident fanned edge is forbidden - - The algo that allows to build the topology of fans - - 1) Compute fanned edges : use threshold angle between adjacent faces as - user parameter - 2) If one model vertex is connected to one single fanned edge - -) If the model vertex is in the symmetry plane --> OK - -) If the number of incident edges is 2 --> add the second one as a fan - -) If more that 1 other edge is not fanned --> ask the user to choose - -) Repeat 2) until everything is OK - 3) Create sets of model faces that are NOT connected by fans and therefore that - are considered as equivalent -*/ - -// return the edges connected to a vertex for this volume - -struct fanTopology { - std::set<GVertex*> corners; - std::set<GVertex*> endings; - std::set<GEdge*> fans; - std::vector< std::set<GFace *> > groups; - bool isFan (GEdge* ge) const {return fans.find(ge) != fans.end();} - int getGroupNum (GFace *gf) const - { - for (unsigned int i=0; i< groups.size(); i++){ - if (std::find(groups[i].begin(),groups[i].end(),gf) != groups[i].end())return i; - } - return -1; - } - fanTopology (GRegion * gr, const std::set<GEdge*> &detectedFans, const std::set<GVertex*> &sym, BoundaryLayerField *blf ); -}; - -static std::list<GEdge*> edges (GVertex* gv, GRegion* gr) { - std::list<GEdge*> er = gr->edges(); - std::list<GEdge*> ev = gv->edges(); - std::list<GEdge*> e ; - - for (std::list<GEdge*>::iterator ite = ev.begin() ; ite !=ev.end() ; ite++){ - if (std::find (er.begin(), er.end(), *ite) != er.end())e.push_back(*ite); - } - return e; -} - -static GFace *otherSideOfEdge (GRegion * gr, GFace *gf, GEdge *ge) -{ - std::list<GFace*> fe = ge->faces(); - std::list<GFace*> fr = gr->faces(); - for (std::list<GFace*>::iterator it = fe.begin(); it != fe.end(); ++it){ - if ((*it) != gf && std::find(fr.begin(), fr.end(), *it) != fr.end()) - return *it; - } - // printf("ouille autre cote de face %d par arerte %d dans region %d foireux\n",gf->tag(),ge->tag(),gr->tag()); - return 0; -} -fanTopology :: fanTopology (GRegion * gr, const std::set<GEdge*> &detectedFans, const std::set<GVertex*> &sym, BoundaryLayerField *blf ) -{ - fans = detectedFans; - endings = sym; - std::list<GVertex*> vs = gr->vertices(); - while (1){ - unsigned int nb = fans.size(); - for (std::list<GVertex*>::iterator it = vs.begin() ; it != vs.end(); it++){ - GVertex *gv = *it; - std::list<GEdge*> e = edges (gv, gr); - std::list<GEdge*> fe ; - for (std::list<GEdge*>::iterator ite = e.begin() ; ite !=e.end() ; ite++) - if (isFan(*ite))fe.push_back(*ite); - if (fe.size() == 1){ - if (endings.find(gv) != endings.end()) continue; - else if (e.size() == 2)fans.insert(e.begin(), e.end()); - else Msg::Fatal("Ensure that it is possible to find closed loops in BL fans !"); - } - } - if (nb == fans.size())break; - } - for (std::list<GVertex*>::iterator it = vs.begin() ; it != vs.end(); it++){ - GVertex *gv = *it; - std::list<GEdge*> e = edges (gv, gr); - std::list<GEdge*> fe ; - for (std::list<GEdge*>::iterator ite = e.begin() ; ite !=e.end() ; ite++) - if (isFan(*ite))fe.push_back(*ite); - // printf("%d fans connected to vert %d\n",fe.size(),gv->tag(), e.size()); - if (fe.size() > 2)corners.insert(gv); - } - - std::list<GFace*> fs = gr->faces(); - - while (!fs.empty()) { - GFace *gf = *fs.begin(); - std::set<GFace *> groupOfFaces; - groupOfFaces.insert(gf); - std::stack<GFace*> _stack; - _stack.push(gf); - // printf("pushing %d\n",gf->tag()); - while(!_stack.empty()){ - gf = _stack.top(); - _stack.pop(); - std::list<GEdge*> ed = gf->edges(); - for (std::list<GEdge*>::iterator ite = ed.begin() ; ite !=ed.end() ; ite++){ - if (!isFan(*ite) && !blf->isEdgeBLSaved((*ite)->tag())){ - GFace *otherSide = otherSideOfEdge (gr,gf,*ite); - if (otherSide && groupOfFaces.find(otherSide) == groupOfFaces.end()){ - groupOfFaces.insert(otherSide); - _stack.push(otherSide); - // printf("pushing %d through %d\n",otherSide->tag(),(*ite)->tag()); - } - } - } - } - groups.push_back(groupOfFaces); - std::list<GFace*> fsb; - for (std::list<GFace*>::iterator it = fs.begin() ; it != fs.end() ; it++){ - if (groupOfFaces.find(*it) == groupOfFaces.end())fsb.push_back(*it); - } - fs = fsb; - } -} - -// This is the tricky part -// We have to find a vector N that has the following properties -// V = (x,y,z) / (x^2+y^2+z^2)^{1/2} is a point on the unit sphere -// the n[i]'s are points on the unit sphere -// V maximizes min_i (V * n[i]) -// This means I'd like to find point V that is - -/* -static void filterVectors(std::vector<SVector3> &n) -{ - std::vector<SVector3> temp; - temp.push_back(n[0]); - for (unsigned int i = 1 ; i<n.size() ; i++){ - bool found = false; - for (unsigned int j = 0 ; j<temp.size() ; j++){ - double d = dot(n[i],temp[j]); - if (d < 0.98)found = true; - } - if (found) temp.push_back(n[i]); - } - n = temp; -} -*/ - -static SVector3 computeBestNormal(std::vector<SVector3> &n) -{ - // filterVectors (n); - SVector3 V; - if (n.size() == 1)V = n[0]; - else if (n.size() == 2)V = n[0]+n[1]; - else if (n.size() == 3)circumCenterXYZ(n[0],n[1],n[2],V); - else { - Msg::Warning("suboptimal choice for exterior normal: %d vectors to average",n.size()); - for (unsigned int i = 0 ; i<n.size() ; i++)V+=n[i]; - } - V.normalize(); - return V; -} - - -static int createColumnsBetweenFaces(GRegion *gr, - MVertex *myV, - BoundaryLayerField *blf, - BoundaryLayerColumns *_columns, - std::set<GFace*> &_gfaces, - std::multimap<GFace*,MTriangle*> & _faces, - std::map<MFace,SVector3,Less_Face> &_normals, - fanTopology &ft) -{ - SVector3 n[256]; - int count = 0; - GFace *gfs[256]; - - // we compute normals per face using the surface mesh (we could try to use the - // model but I doubt it'd be better, especially if the mesh is coarse - for( std::set<GFace*> ::iterator it = _gfaces.begin() ; it != _gfaces.end(); ++it){ - for (std::multimap<GFace*,MTriangle*>::iterator itm = - _faces.lower_bound(*it); - itm != _faces.upper_bound(*it); ++itm){ - - SVector3 N = _normals[itm->second->getFace(0)]; - n[count] += N; - } - gfs[count] = *it; - n[count].normalize(); - count ++; - } - - // the topology of the fans is known - // we look over all faces and look in which - // group it lies in - - std::vector< std::vector<GFace*> > joints; - - std::multimap<int, GFace*> lGroup; - std::map<GFace*, int> inv; - std::set<int> gs; - for (int i=0;i<count;i++) { - inv[gfs[i]] = i; - int iGroup = ft.getGroupNum (gfs[i]); - gs.insert(iGroup); - lGroup.insert(std::make_pair(iGroup,gfs[i])); - } - - - for (std::set<int>::iterator it = gs.begin(); it != gs.end() ; ++it){ - std::pair<std::multimap<int, GFace*>::iterator, - std::multimap<int, GFace*>::iterator> range = lGroup.equal_range(*it); - std::vector<GFace*> joint; - for (std::multimap<int, GFace*>::iterator itm = range.first ; - itm != range.second ; itm++) - joint.push_back(itm->second); - joints.push_back(joint); - // SVector3 avg (0,0,0); - std::vector<SVector3> ns; - - for (unsigned int i=0;i<joint.size(); i++){ - ns.push_back( n[inv[joint[i]]] ); - // avg += n[inv[joint[i]]]; - } - SVector3 avg = computeBestNormal(ns); - - std::vector<MVertex*> _column; - std::vector<SMetric3> _metrics; - avg.normalize(); - createBLPointsInDir (gr,myV,blf,avg,_column,_metrics); - _columns->addColumn(avg,myV, _column, _metrics, joint); - } - - // // DEBUG STUFF - // if (myV->onWhat()->dim() == 0 && myV->onWhat()->tag() == 6){ - // printf("%d %d\n",gs.size(),joints.size()); - // } - - // create wedges - if (joints.size() > 1){ - for (unsigned int I = 0 ; I < joints.size() ; I++){ - const BoundaryLayerData & c0 = _columns->getColumn(myV, I); - for (unsigned int J = I+1 ; J < joints.size() ; J++){ - const BoundaryLayerData & c1 = _columns->getColumn(myV, J); - std::vector<SVector3> shoot; - createWedgeBetweenTwoFaces(myV,c0._n,c1._n,shoot); - for (unsigned int i=1;i<shoot.size()-1;i++){ - std::vector<MVertex*> _column; - std::vector<SMetric3> _metrics; - createBLPointsInDir (gr,myV,blf,shoot[i],_column,_metrics); - _columns->addColumn(shoot[i] , myV, _column, _metrics); - } - } - } - } - // we have a corner : in a first step, only add one single - // in the average direction - if (joints.size() > 2){ - } - - return joints.size(); -} - -static void createColumnsOnSymmetryPlane(MVertex *myV, - BoundaryLayerColumns *_columns, - std::set<GFace*> &_allGFaces, - std::list<GFace*> &faces, - fanTopology &ft) -{ - // get all model faces for that vertex that have boundary layer columns attached - for ( std::list<GFace*>::iterator itf = faces.begin(); itf!= faces.end() ; ++itf){ - BoundaryLayerColumns* _face_columns = (*itf)->getColumns(); - int N = _face_columns->getNbColumns(myV); - if (N == 1){ - std::vector<GFace*> _joint; - _joint.insert(_joint.begin(),_allGFaces.begin(),_allGFaces.end()); - const BoundaryLayerData & c = _face_columns->getColumn(myV,0); - _columns->addColumn(c._n,myV, c._column, c._metrics, _joint); - } - else if (N > 1){ - if (_allGFaces.size() != 2){ - Msg::Fatal("cannot solve such a strange stuff in the BL"); - } - // printf("%d columns\n",N); - std::set<GFace*>::iterator itff = _allGFaces.begin(); - GFace *g1 = *itff ; ++itff; GFace *g2 = *itff; - bool sense = true; - std::vector<GFace*> _joint; - - const BoundaryLayerFan *fan = _face_columns->getFan(myV); - - if (fan){ - MVertex *v11 = fan->_e1.getVertex(0); - MVertex *v12 = fan->_e1.getVertex(1); - std::list<GEdge*> l1 = g1->edges(); - std::list<GEdge*> l2 = g2->edges(); - if (v11 == myV){ - if (v12->onWhat()->dim() == 1){ - GEdge *ge1 = (GEdge*)v12->onWhat(); - if (std::find(l1.begin(),l1.end(),ge1) != l1.end())sense = fan->sense; - else if (std::find(l2.begin(),l2.end(),ge1) != l2.end())sense = !fan->sense; - } - else - Msg::Error("Cannot choose between directions in a BL (dim = %d)", - v12->onWhat()->dim()); - } - else { - if (v11->onWhat()->dim() == 1){ - GEdge *ge1 = (GEdge*)v11->onWhat(); - if (std::find(l1.begin(),l1.end(),ge1) != l1.end())sense = fan->sense; - else if (std::find(l2.begin(),l2.end(),ge1) != l2.end())sense = !fan->sense; - } - else Msg::Error("Cannot choose between directions in a BL"); - } - } - else{ - Msg::Error("No fan on the outgoing BL"); - } - _joint.push_back(g1); - const BoundaryLayerData & c0 = _face_columns->getColumn(myV,sense ? 0 : N-1); - _columns->addColumn(c0._n,myV, c0._column, c0._metrics,_joint); - _joint.clear(); - _joint.push_back(g2); - const BoundaryLayerData & cN = _face_columns->getColumn(myV,sense ? N-1 : 0); - _columns->addColumn(cN._n,myV, cN._column, cN._metrics,_joint); - if (sense){ - for (int k=1;k<N-1;k++){ - const BoundaryLayerData & c = _face_columns->getColumn(myV,k); - _columns->addColumn(c._n,myV, c._column, c._metrics); - } - } - else { - for (int k=N-2;k>0;k--){ - const BoundaryLayerData & c = _face_columns->getColumn(myV,k); - _columns->addColumn(c._n,myV, c._column, c._metrics); - } - } - } - } -} - -static bool preprocessVertex (MVertex *v, - std::map<MTriangle*,GFace*> &_gfaces, - BoundaryLayerColumns * _columns, - std::list<GFace*> &faces, - std::multimap<GFace*,MTriangle*> &_faces, - std::set<GFace*> &_allGFaces){ - faces = v->onWhat()->faces(); - for (std::multimap<MVertex*,MTriangle*>::iterator itm = - _columns->_non_manifold_faces.lower_bound(v); - itm != _columns->_non_manifold_faces.upper_bound(v); ++itm){ - GFace *gf = _gfaces[itm->second]; - _faces.insert(std::make_pair(gf,itm->second)); - _allGFaces.insert(gf); - } - - bool onSymmetryPlane = false; - if (v->onWhat()->dim() != 2) - if (faces.size() != _allGFaces.size()) - onSymmetryPlane = true; - return onSymmetryPlane; -} - -bool buildAdditionalPoints3D(GRegion *gr) -{ - BoundaryLayerField *blf = getBLField (gr->model()); - - if (!blf) return false; - - blf->setupFor3d(); - - BoundaryLayerColumns *_columns = gr->getColumns(); - - std::list<GFace*> faces = gr->faces(); - std::list<GFace*>::iterator itf = faces.begin(); - std::set<MVertex*> _vertices; - std::map<MFace,SVector3,Less_Face> _normals; - std::map<MTriangle*,GFace*> _gfaces; - - // filter vertices : belong to BL and are classified on FACES - while(itf != faces.end()){ - if (blf->isFaceBL((*itf)->tag())){ - // printf("FACE %d is a boundary layer face %d triangles\n",(*itf)->tag(), - // (int)(*itf)->triangles.size()); - for(unsigned int i = 0; i< (*itf)->triangles.size(); i++){ - _gfaces[(*itf)->triangles[i]] = *itf; - _columns->_inverse_classification [(*itf)->triangles[i]->getFace(0)] = *itf; - _normals [(*itf)->triangles[i]->getFace(0)] = SVector3(0,0,0); - for(unsigned int j = 0; j< 3; j++){ - if ((*itf)->triangles[i]->getVertex(j)->onWhat()->dim() != 3){ - _columns->_non_manifold_faces.insert - (std::make_pair((*itf)->triangles[i]->getVertex(j),(*itf)->triangles[i])); - _vertices.insert((*itf)->triangles[i]->getVertex(j)); - } - } - } - } - ++itf; - } - // printf("%d vertices \n", (int)_vertices.size()); - - // assume that the initial mesh has been created i.e. that there exist - // tetrahedra inside the domain. Tetrahedra are used to define - // exterior normals - for (unsigned int i=0;i<gr->tetrahedra.size();i++){ - for (int j=0;j<4;j++){ - MFace f = gr->tetrahedra[i]->getFace(j); - std::map<MFace,SVector3,Less_Face>::iterator it = _normals.find(f); - if (it != _normals.end()){ - MVertex *v0 = f.getVertex(0); - MVertex *v1 = f.getVertex(1); - MVertex *v2 = f.getVertex(2); - MVertex *v3 = 0; - for (int k=0;k<4;k++){ - if (gr->tetrahedra[i]->getVertex(k) != v0 && - gr->tetrahedra[i]->getVertex(k) != v1 && - gr->tetrahedra[i]->getVertex(k) != v2 ){ - v3 = gr->tetrahedra[i]->getVertex(k); - } - } - SVector3 v01 (v1->x()-v0->x(),v1->y()-v0->y(),v1->z()-v0->z()); - SVector3 v02 (v2->x()-v0->x(),v2->y()-v0->y(),v2->z()-v0->z()); - SVector3 v03 (v3->x()-v0->x(),v3->y()-v0->y(),v3->z()-v0->z()); - SVector3 n = crossprod (v01,v02); - double sign = dot(n,v03); - n.normalize(); - if (sign > 0)it->second = n; - else it->second = n*(-1.0); - if (_columns->_normals3D.find(it->first) != _columns->_normals3D.end()) - printf("aaaaaaaarghhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhh\n"); - _columns->_normals3D.insert(std::make_pair(it->first,it->second)); - } - } - } - - // look for all the wedges - std::set<GEdge*> fans; - std::set<GVertex*> fanNodes; - for (std::set<MVertex*>::iterator it = _vertices.begin(); it != _vertices.end() ; ++it){ - std::list<GFace*> faces; - std::multimap<GFace*,MTriangle*> _faces; - std::set<GFace*> _allGFaces; - preprocessVertex (*it, _gfaces, _columns, faces, _faces, _allGFaces); - if ((*it)->onWhat()->dim() == 0){ - GVertex *gv = static_cast<GVertex*>((*it)->onWhat()); - if (gv && blf->isFanNode(gv->tag())){ - fanNodes.insert(gv); - } - } - else if ((*it)->onWhat()->dim() == 1){ - GEdge *ge = static_cast<GEdge*>((*it)->onWhat()); - if (ge && blf->isFan(ge->tag())){ - fans.insert(ge); - } - } - } - - // printf("STARTING ANALYSIS OF TOPOLOGY (%d fan nodes %d fan edges\n",fanNodes.size(),fans.size()); - - fanTopology ft (gr, fans, fanNodes, blf); - - Msg::Info("BL Topology for region %d : %d FANS %d CORNERS %d GROUPS %d ENDINGS", - gr->tag(),ft.fans.size(),ft.corners.size(),ft.groups.size(),ft.endings.size()); - - // for all boundry points - for (std::set<MVertex*>::iterator it = _vertices.begin(); it != _vertices.end() ; ++it){ - std::list<GFace*> faces; - std::multimap<GFace*,MTriangle*> _faces; - std::set<GFace*> _allGFaces; - bool onSymmetryPlane = preprocessVertex (*it, _gfaces, _columns, faces, _faces, _allGFaces); - - if (onSymmetryPlane){ - // we have a 3D boundary layer that connects a 2D boundary layer - // this is the tricky case - createColumnsOnSymmetryPlane(*it,_columns, _allGFaces, faces, ft); - } - else { - // internal columns (inside the volume) - createColumnsBetweenFaces (gr,*it,blf,_columns,_allGFaces,_faces,_normals,ft); - } - } - - // DEBUG STUFF - FILE *f = Fopen("POINTS3D.pos","w"); - if(f){ - fprintf(f,"View \"\" {\n"); - for (std::set<MVertex*>::iterator it = _vertices.begin(); it != _vertices.end() ; ++it){ - MVertex *v = *it; - for (int i=0;i<_columns->getNbColumns(v);i++){ - const BoundaryLayerData &data = _columns->getColumn(v,i); - for (unsigned int j=0;j<data._column.size();j++){ - MVertex *blv = data._column[j]; - fprintf(f,"SP(%g,%g,%g){%d};\n",blv->x(),blv->y(),blv->z(),v->getNum()); - } - } - } - fprintf(f,"};\n"); - fclose (f); - } - // END OF DEBUG STUFF - - return true; -} #endif diff --git a/Geo/boundaryLayersData.h b/Geo/boundaryLayersData.h index 419dba893a6bf644f0b64c4dd3a45fe885d4bfc4..76fc336e13ac368936e1ec4b53ed6df0da005103 100644 --- a/Geo/boundaryLayersData.h +++ b/Geo/boundaryLayersData.h @@ -8,6 +8,7 @@ #include "SVector3.h" #include "STensor3.h" +#include "MElement.h" #include "MEdge.h" #include "MFace.h" #include <map> @@ -24,18 +25,13 @@ struct BoundaryLayerData { SVector3 _n; std::vector<MVertex*> _column; - std::vector<SMetric3> _metrics; - std::vector<GFace*> _joint; + // std::vector<SMetric3> _metrics; + // std::vector<GFace*> _joint; BoundaryLayerData(){} BoundaryLayerData(const SVector3 & dir, - std::vector<MVertex*> column, - std::vector<SMetric3> metrics) - : _n(dir), _column(column), _metrics(metrics){} - BoundaryLayerData(const SVector3 & dir, - std::vector<MVertex*> column, - std::vector<SMetric3> metrics, - std::vector<GFace*> joint) - : _n(dir), _column(column), _metrics(metrics),_joint(joint){} + std::vector<MVertex*> column/*, + std::vector<SMetric3> metrics*/) + : _n(dir), _column(column) /*,_metrics(metrics)*/{} }; struct BoundaryLayerFan @@ -51,20 +47,6 @@ struct edgeColumn { : _c1(c1), _c2(c2){} }; -struct faceColumn { - const BoundaryLayerData &_c1, &_c2, &_c3, &_c4; - faceColumn(const BoundaryLayerData &c1, - const BoundaryLayerData &c2, - const BoundaryLayerData &c3) - : _c1(c1), _c2(c2), _c3(c3), _c4(c3){} - faceColumn(const BoundaryLayerData &c1, - const BoundaryLayerData &c2, - const BoundaryLayerData &c4, - const BoundaryLayerData &c3) - : _c1(c1), _c2(c2), _c3(c3), _c4(c4){} -}; - - class BoundaryLayerColumns { std::map<MVertex*, BoundaryLayerFan> _fans; @@ -79,26 +61,30 @@ public: typedef std::multimap<MVertex*,BoundaryLayerData>::iterator iter; typedef std::map<MVertex*, BoundaryLayerFan>::iterator iterf; std::multimap<MVertex*, MVertex*> _non_manifold_edges; - std::multimap<MVertex*,MTriangle*> _non_manifold_faces; std::multimap<MEdge, SVector3, Less_Edge> _normals; - std::multimap<MFace, SVector3, Less_Face> _normals3D; + void clearData () { + _toFirst.clear(); + _elemColumns.clear(); + _inverse_classification.clear(); + _data.clear(); + _normals.clear(); + _non_manifold_edges.clear(); + _elemColumns.clear(); + _fans.clear(); + } + iter begin() { return _data.begin(); } iter end() { return _data.end(); } iterf beginf() { return _fans.begin(); } iterf endf() { return _fans.end(); } BoundaryLayerColumns (){} inline void addColumn(const SVector3 &dir, MVertex* v, - std::vector<MVertex*> _column, - std::vector<SMetric3> _metrics) - { - _data.insert (std::make_pair(v,BoundaryLayerData(dir, _column,_metrics))); - } - inline void addColumn(const SVector3 &dir, MVertex* v, - std::vector<MVertex*> _column, - std::vector<SMetric3> _metrics, - std::vector<GFace*> _joint) + std::vector<MVertex*> _column//, + // std::vector<SMetric3> _metrics, + // std::vector<GFace*> _joint + ) { - _data.insert (std::make_pair(v,BoundaryLayerData(dir, _column,_metrics,_joint))); + _data.insert (std::make_pair(v,BoundaryLayerData(dir, _column/*,_metrics,_joint*/))); } inline void addFan(MVertex *v, MEdge e1, MEdge e2, bool s) { @@ -113,7 +99,7 @@ public: return 0; } - const BoundaryLayerData &getColumn(MVertex *v, MFace f) const; + // const BoundaryLayerData &getColumn(MVertex *v, MFace f) const; inline const BoundaryLayerData &getColumn(MVertex *v, MEdge e) const { @@ -132,7 +118,7 @@ public: return error; } edgeColumn getColumns(MVertex *v1, MVertex *v2 , int side); - faceColumn getColumns(GFace *gf, MVertex *v1, MVertex *v2 , MVertex* v3, int side); + // faceColumn getColumns(GFace *gf, MVertex *v1, MVertex *v2 , MVertex* v3, int side); inline int getNbColumns(MVertex *v) const { return _data.count(v); } inline const BoundaryLayerData &getColumn(MVertex *v, int iColumn) const { diff --git a/Mesh/BackgroundMeshTools.cpp b/Mesh/BackgroundMeshTools.cpp index fe6a091a6a816ef38b4ff036915cfb65d19e4049..4795e374f00a55fa40102b2f25aa8523003d738c 100644 --- a/Mesh/BackgroundMeshTools.cpp +++ b/Mesh/BackgroundMeshTools.cpp @@ -66,6 +66,7 @@ static double LC_MVertex_CURV(GEntity *ge, double U, double V) GEdge *ged = (GEdge *)ge; Crv = ged->curvature(U); Crv = std::max(Crv, max_surf_curvature(ged, U)); + // printf("%g %d\n",Crv, CTX::instance()->mesh.minCircPoints); // Crv = max_surf_curvature(ged, U); } break; diff --git a/Mesh/Field.cpp b/Mesh/Field.cpp index 3927929f18976f44bc5cd1f38b30c73088be9099..6a20fa24df4aa2368feec545ae504344fdcb627c 100644 --- a/Mesh/Field.cpp +++ b/Mesh/Field.cpp @@ -2199,7 +2199,7 @@ std::string BoundaryLayerField::getDescription() BoundaryLayerField::BoundaryLayerField() { hwall_n = .1; - hwall_t = .5; + // hwall_t = .5; hfar = 1; ratio = 1.1; thickness = 1.e-2; @@ -2207,20 +2207,15 @@ BoundaryLayerField::BoundaryLayerField() tgt_aniso_ratio = 1.e10; iRecombine = 0; iIntersect = 0; - options["NodesList"] = new FieldOptionList - (nodes_id, "Indices of nodes in the geometric model", &update_needed); options["EdgesList"] = new FieldOptionList (edges_id, "Indices of curves in the geometric model for which a boundary " "layer is needed", &update_needed); - options["FacesList"] = new FieldOptionList - (faces_id, "Indices of faces in the geometric model for which a boundary " - "layer is needed", &update_needed); - options["FansList"] = new FieldOptionList - (fans_id, "Indices of edges in the geometric model for which a fan " - "is created", &update_needed); options["FanNodesList"] = new FieldOptionList (fan_nodes_id, "Indices of vertices in the geometric model for which a fan " "is created", &update_needed); + options["NodesList"] = new FieldOptionList + (nodes_id, "Indices of vertices in the geometric model for which a BL " + "ends", &update_needed); options["Quads"] = new FieldOptionInt (iRecombine, "Generate recombined elements in the boundary layer"); options["IntersectMetrics"] = new FieldOptionInt @@ -2231,8 +2226,8 @@ BoundaryLayerField::BoundaryLayerField() // (fan_angle, "Threshold angle for creating a mesh fan in the boundary layer"); options["AnisoMax"] = new FieldOptionDouble (tgt_aniso_ratio, "Threshold angle for creating a mesh fan in the boundary layer"); - options["hwall_t"] = new FieldOptionDouble - (hwall_t, "Mesh Size Tangent to the Wall"); + // options["hwall_t"] = new FieldOptionDouble + // (hwall_t, "Mesh Size Tangent to the Wall"); options["ratio"] = new FieldOptionDouble (ratio, "Size Ratio Between Two Successive Layers"); options["hfar"] = new FieldOptionDouble @@ -2250,18 +2245,13 @@ void BoundaryLayerField::removeAttractors() } void BoundaryLayerField::setupFor1d(int iE) { - - if (faces_id_saved.empty() && - edges_id_saved.empty() && - faces_id_saved.empty() ){ - faces_id_saved = faces_id; + if (edges_id_saved.empty() ){ edges_id_saved = edges_id; nodes_id_saved = nodes_id; } nodes_id.clear(); edges_id.clear(); - faces_id.clear(); bool found = std::find(edges_id_saved.begin(), edges_id_saved.end(), iE) != edges_id_saved.end(); @@ -2289,17 +2279,13 @@ void BoundaryLayerField::setupFor2d(int iF) remove GFaces from the attarctors (only used in 2D) for edges and vertices */ - if (faces_id_saved.empty() && - edges_id_saved.empty() && - faces_id_saved.empty() ){ - faces_id_saved = faces_id; + if (edges_id_saved.empty()){ edges_id_saved = edges_id; nodes_id_saved = nodes_id; } nodes_id.clear(); edges_id.clear(); - faces_id.clear(); // printf("have %d %d\n",faces_id_saved.size(),edges_id_saved.size()); @@ -2313,9 +2299,7 @@ void BoundaryLayerField::setupFor2d(int iF) std::list<GEdge*> embedded_edges = gf->embeddedEdges(); ed.insert(ed.begin(), embedded_edges.begin(),embedded_edges.end()); - - - // printf("face %d has %d edges\n",iF,ed.size()); + // printf("face %d has %d edges\n",iF,ed.size()); for (std::list<GEdge*>::iterator it = ed.begin(); it != ed.end() ; ++it){ bool isIn = false; @@ -2327,22 +2311,9 @@ void BoundaryLayerField::setupFor2d(int iF) if (found){ std::list<GFace*> fc = (*it)->faces(); // one only face --> 2D --> BL - if (fc.size() == 1) isIn = true; + if (fc.size() <= 1) isIn = true; else { - // more than one face and - std::list<GFace*>::iterator itf = fc.begin(); - bool found_this = std::find(faces_id_saved.begin(), faces_id_saved.end(), iF) != - faces_id_saved.end(); - if (!found_this)isIn = true; - else { - bool foundAll = true; - for ( ; itf != fc.end() ; ++itf){ - int iF2 = (*itf)->tag(); - foundAll &= std::find(faces_id_saved.begin(), faces_id_saved.end(), iF2) != - faces_id_saved.end(); - } - if(foundAll) isIn = true; - } + Msg::Error ("Only 2D Boundary Layers are supported (edge %d is adjacet to %d faces\n",iE,fc.size()); } } if (isIn){ @@ -2355,12 +2326,6 @@ void BoundaryLayerField::setupFor2d(int iF) removeAttractors(); } -void BoundaryLayerField::setupFor3d() -{ - faces_id = faces_id_saved; - removeAttractors(); -} - double BoundaryLayerField::operator() (double x, double y, double z, GEntity *ge) { if (update_needed){ @@ -2372,10 +2337,6 @@ double BoundaryLayerField::operator() (double x, double y, double z, GEntity *ge it != edges_id.end(); ++it) { _att_fields.push_back(new AttractorField(1,*it,300000)); } - for(std::list<int>::iterator it = faces_id.begin(); - it != faces_id.end(); ++it) { - _att_fields.push_back(new AttractorField(2,*it,1200)); - } update_needed = false; } @@ -2442,6 +2403,9 @@ void BoundaryLayerField::operator() (AttractorField *cc, double dist, double x, double y, double z, SMetric3 &metr, GEntity *ge) { + + // printf("WHAT THE FUCK\n"); + // dist = hwall -> lc = hwall * ratio // dist = hwall (1+ratio) -> lc = hwall ratio ^ 2 // dist = hwall (1+ratio+ratio^2) -> lc = hwall ratio ^ 3 @@ -2454,8 +2418,8 @@ void BoundaryLayerField::operator() (AttractorField *cc, double dist, const double ll1 = dist*(ratio-1) + hwall_n; double lc_n = std::min(ll1,hfar); - const double ll2 = dist*(ratio-1) + hwall_t; - double lc_t = std::min(lc_n*CTX::instance()->mesh.anisoMax, std::min(ll2,hfar)); + // const double ll2 = dist*(ratio-1) + hwall_t; + double lc_t = std::min(lc_n*CTX::instance()->mesh.anisoMax, hfar/*std::min(ll2,hfar)*/); lc_n = std::max(lc_n, CTX::instance()->mesh.lcMin); lc_n = std::min(lc_n, CTX::instance()->mesh.lcMax); @@ -2535,10 +2499,6 @@ void BoundaryLayerField::operator() (double x, double y, double z, it != edges_id.end(); ++it) { _att_fields.push_back(new AttractorField(1,*it,10000)); } - for(std::list<int>::iterator it = faces_id.begin(); - it != faces_id.end(); ++it) { - _att_fields.push_back(new AttractorField(2,*it,1200)); - } update_needed = false; } diff --git a/Mesh/Field.h b/Mesh/Field.h index bbc1ed23cafcf7f9bb51dcfc6a9efc9b5e335189..df99fad2a5124b44be33e8e5178f49ed51744901 100644 --- a/Mesh/Field.h +++ b/Mesh/Field.h @@ -139,12 +139,12 @@ class AttractorField; class BoundaryLayerField : public Field { private: std::list<AttractorField *> _att_fields; - std::list<int> nodes_id, edges_id, faces_id; - std::list<int> faces_id_saved, edges_id_saved, nodes_id_saved, fans_id, fan_nodes_id; + std::list<int> nodes_id, edges_id; + std::list<int> edges_id_saved, nodes_id_saved, fan_nodes_id; void operator() (AttractorField *cc, double dist, double x, double y, double z, SMetric3 &metr, GEntity *ge); public: - double hwall_n,hwall_t,ratio,hfar,thickness,fan_angle; + double hwall_n,/*hwall_t,*/ratio,hfar,thickness,fan_angle; double current_distance, tgt_aniso_ratio; SPoint3 _closest_point; int iRecombine, iIntersect; @@ -156,10 +156,6 @@ class BoundaryLayerField : public Field { ~BoundaryLayerField() {removeAttractors();} virtual double operator() (double x, double y, double z, GEntity *ge=0); virtual void operator() (double x, double y, double z, SMetric3 &metr, GEntity *ge=0); - bool isFaceBL (int iF) const - { - return std::find(faces_id.begin(),faces_id.end(),iF) != faces_id.end(); - } bool isEdgeBL (int iE) const { return std::find(edges_id.begin(),edges_id.end(),iE) != edges_id.end(); @@ -169,22 +165,17 @@ class BoundaryLayerField : public Field { return std::find(edges_id_saved.begin(),edges_id_saved.end(),iE) != edges_id_saved.end(); } - bool isFan (int iE) const - { - return std::find(fans_id.begin(),fans_id.end(),iE) != fans_id.end(); - } bool isFanNode (int iV) const { return std::find(fan_nodes_id.begin(),fan_nodes_id.end(),iV) != fan_nodes_id.end(); } - bool isVertexBL (int iV) const + bool isEndNode (int iV) const { return std::find(nodes_id.begin(),nodes_id.end(),iV) != nodes_id.end(); } void computeFor1dMesh(double x, double y, double z, SMetric3 &metr); void setupFor1d(int iE); void setupFor2d(int iF); - void setupFor3d(); void removeAttractors(); }; diff --git a/Mesh/filterElements.cpp b/Mesh/filterElements.cpp index 380838fcadd317e72300195cef16e2f3b51c3c80..5990306d09dd039acb56e153973925dc94b8a42c 100644 --- a/Mesh/filterElements.cpp +++ b/Mesh/filterElements.cpp @@ -8,14 +8,12 @@ #include <set> #include "GmshDefines.h" #include "filterElements.h" -#include "fullMatrix.h" -#include "GaussIntegration.h" #include "MElement.h" #include "MTriangle.h" #include "MQuadrangle.h" -#include "MPrism.h" -#include "MHexahedron.h" +#include "MLine.h" #include "rtree.h" +#include "robustPredicates.h" void MElementBB(void *a, double *min, double *max); int MElementInEle(void *a, double *x); @@ -32,89 +30,113 @@ struct MElement_Wrapper } }; -static bool inBB (double *mi, double *ma, double *x){ - if (x[0] < mi[0])return false; - if (x[1] < mi[1])return false; - if (x[2] < mi[2])return false; - if (x[0] > ma[0])return false; - if (x[1] > ma[1])return false; - if (x[2] > ma[2])return false; - return true; + +/** OVERLAP TEST IN 2D + only use predicate orient2D :-) + +2 cases + +1--> + + *---------* + | | + | *--------* + | | | | + *---------* + | | | + *--------* + +2--> + +**/ + +inline double orientationTest (double a[2], double b[2], double c[2]){ + double s = -robustPredicates::orient2d(a,b,c); + return s > 0 ? 1.0 : s < 0 ? -1.0 : 0.0; } -bool rtree_callback(MElement *e1,void* pe2) -{ - MElement_Wrapper *wrapper = static_cast<MElement_Wrapper*>(pe2); - MElement *e2 = wrapper->_e; +inline double orientationTest (MVertex *va, MVertex *vb, MVertex *vc){ + double a[2] = {va->x(),va->y()}; + double b[2] = {vb->x(),vb->y()}; + double c[2] = {vc->x(),vc->y()}; + return orientationTest (a,b,c); +} - if (std::binary_search(wrapper->_notOverlap.begin(),wrapper->_notOverlap.end(),e1)) - return true; +inline double orientationTest (SVector3 &va, SVector3 &vb, SVector3 &vc){ + double a[2] = {va.x(),va.y()}; + double b[2] = {vb.x(),vb.y()}; + double c[2] = {vc.x(),vc.y()}; + return orientationTest (a,b,c); +} - for (int i=0;i<e1->getNumVertices();i++){ - for (int j=0;j<e2->getNumVertices();j++){ - if(e1->getVertex(i) == e2->getVertex(j))return true; - } - } - double min2[3],max2[3]; - MElementBB(e2,min2,max2); +bool intersectEdge2d(const MEdge &ed1, const MEdge &ed2) { - for (int i=0;i<e1->getNumVertices();i++){ - SPoint3 xyz (e1->getVertex(i)->x(),e1->getVertex(i)->y(),e1->getVertex(i)->z()); - if (inBB (min2,max2,xyz)){ - if (MElementInEle(e2,xyz)){ - wrapper->_overlap = true; - return false; - } - } - } + /* SVector3 a1(ed1.getVertex(0)->x(), ed1.getVertex(0)->y(), 0); + SVector3 a2(ed1.getVertex(1)->x(), ed1.getVertex(1)->y(), 0); - double min1[3],max1[3]; - MElementBB(e1,min1,max1); - for (int i=0;i<e2->getNumVertices();i++){ - SPoint3 xyz (e2->getVertex(i)->x(),e2->getVertex(i)->y(),e2->getVertex(i)->z()); - if (inBB(min1,max1,xyz)){ - if (MElementInEle(e1,xyz)){ - wrapper->_overlap = true; - return false; - } - } - } + SVector3 b1(ed2.getVertex(0)->x(), ed2.getVertex(0)->y(), 0); + SVector3 b2(ed2.getVertex(1)->x(), ed2.getVertex(1)->y(), 0); - // return false; + SVector3 a = (a1+a2)*0.5; + SVector3 b = (b1+b2)*0.5; - fullMatrix<double> pts1,pts2; - fullVector<double> weights; + SVector3 a1l = a + (a2-a1)*0.55; + SVector3 a2l = a - (a2-a1)*0.55; + + SVector3 b1l = b + (b2-b1)*0.55; + SVector3 b2l = b - (b2-b1)*0.55; - gaussIntegration::get (e1->getType(),1,pts1,weights); - gaussIntegration::get (e2->getType(),1,pts2,weights); + if (orientationTest (a1l, a2l, b1l) * orientationTest (a1l, a2l, b2l) <= 0 && + orientationTest (b1l, b2l, a1l) * orientationTest (b1l, b2l, a2l) <= 0 ) + return true; + */ + if (ed1.getVertex(0) == ed2.getVertex(0) || + ed1.getVertex(0) == ed2.getVertex(1) || + ed1.getVertex(1) == ed2.getVertex(0) || + ed1.getVertex(1) == ed2.getVertex(1) ) return false; + + if ((orientationTest (ed1.getVertex(0),ed1.getVertex(1),ed2.getVertex(0)) * + orientationTest (ed1.getVertex(0),ed1.getVertex(1),ed2.getVertex(1)) <= 0) && + (orientationTest (ed2.getVertex(0),ed2.getVertex(1),ed1.getVertex(0)) * + orientationTest (ed2.getVertex(0),ed2.getVertex(1),ed1.getVertex(1)) <= 0)) + return true; + return false; +} - for (int i=0;i<pts1.size1();i++){ - double u = pts1(i,0); - double v = pts1(i,1); - double w = pts1(i,2); - SPoint3 xyz; - e1->pnt(u,v,w,xyz); - if (inBB(min2,max2,xyz)){ - if (MElementInEle(e2,xyz)){ - wrapper->_overlap = true; - return false; +bool overlap2D (MElement *e1, MElement *e2) { + for (int i=0;i<e1->getNumEdges();i++){ + MEdge ed1 = e1->getEdge (i); + for (int j=0;j<e2->getNumEdges();j++){ + MEdge ed2 = e2->getEdge (j); + if (intersectEdge2d(ed1,ed2)){ + // printf("apero time \n"); + return true; } } } - for (int i=0;i<pts2.size1();i++){ - double u = pts2(i,0); - double v = pts2(i,1); - double w = pts2(i,2); - SPoint3 xyz; - e2->pnt(u,v,w,xyz); - if (inBB(min1,max1,xyz)){ - if (MElementInEle(e1,xyz)){ - wrapper->_overlap = true; - return false; - } - } + return false; +} + +bool rtree_callback(MElement *e1,void* pe2) +{ + MElement_Wrapper *wrapper = static_cast<MElement_Wrapper*>(pe2); + MElement *e2 = wrapper->_e; + + if (std::binary_search(wrapper->_notOverlap.begin(),wrapper->_notOverlap.end(),e1)) + return true; + + // for (int i=0;i<e1->getNumVertices();i++){ + // for (int j=0;j<e2->getNumVertices();j++){ + // if(e1->getVertex(i) == e2->getVertex(j))return true; + // } + // } + + if (e1->getDim() <= 2 && e2->getDim() <= 2) { + wrapper->_overlap = overlap2D (e1,e2); + return !wrapper->_overlap; } + Msg::Error("overlapping of elements in 3D not done yet"); return true; } @@ -133,75 +155,47 @@ void filterColumns(std::vector<MElement*> &elem, for (std::map<MElement*,std::vector<MElement*> >::iterator it = _elemColumns.begin(); it !=_elemColumns.end() ; ++it){ const std::vector<MElement*> &c = it->second; - unsigned int MAX = c.size() - 1; + unsigned int MAX = c.size(); + // printf("size of column %d\n",c.size()); for (unsigned int i=0;i<c.size(); i++){ if (!std::binary_search(elem.begin(),elem.end(),c[i])){ MAX = i - 1; break; } } + if (!MAX)MAX=1; // printf("MAX = %d c = %d\n",MAX,c.size()); for (unsigned int i=0;i<MAX;i++){ toKeep.push_back(c[i]); } - for (unsigned int i=MAX;i<c.size();i++){ + // for (unsigned int i=MAX;i<c.size();i++){ /// FIXME !!! // delete c[i]; - } + // } } - printf("%d --> %d\n", (int)elem.size(), (int)toKeep.size()); + // printf("%d --> %d\n", (int)elem.size(), (int)toKeep.size()); elem = toKeep; } -void filterOverlappingElements (std::vector<MTriangle*> &blTris, - std::vector<MQuadrangle*>&blQuads, - std::map<MElement*,std::vector<MElement*> > &_elemColumns, - std::map<MElement*,MElement*> &_toFirst) -{ - std::vector<MElement*> vvv; - vvv.insert(vvv.begin(),blTris.begin(),blTris.end()); - vvv.insert(vvv.begin(),blQuads.begin(),blQuads.end()); - Less_Partition lp; - std::sort(vvv.begin(),vvv.end(), lp); - filterOverlappingElements (vvv,_elemColumns,_toFirst); - filterColumns (vvv,_elemColumns); - blTris.clear(); - blQuads.clear(); - for (unsigned int i=0;i<vvv.size();i++){ - if (vvv[i]->getType() == TYPE_TRI)blTris.push_back((MTriangle*)vvv[i]); - else if (vvv[i]->getType() == TYPE_QUA)blQuads.push_back((MQuadrangle*)vvv[i]); - } -} - -void filterOverlappingElements (std::vector<MPrism*> &blPrisms, - std::vector<MHexahedron*>&blHexes, - std::map<MElement*,std::vector<MElement*> > &_elemColumns, - std::map<MElement*,MElement*> &_toFirst) -{ - printf("filtering !!\n"); - std::vector<MElement*> vvv; - vvv.insert(vvv.begin(),blPrisms.begin(),blPrisms.end()); - vvv.insert(vvv.begin(),blHexes.begin(),blHexes.end()); - Less_Partition lp; - std::sort(vvv.begin(),vvv.end(), lp); - filterOverlappingElements (vvv,_elemColumns,_toFirst); - filterColumns (vvv,_elemColumns); - blPrisms.clear(); - blHexes.clear(); - for (unsigned int i=0;i<vvv.size();i++){ - if (vvv[i]->getType() == TYPE_PRI)blPrisms.push_back((MPrism*)vvv[i]); - else if (vvv[i]->getType() == TYPE_HEX)blHexes.push_back((MHexahedron*)vvv[i]); - } -} -void filterOverlappingElements (std::vector<MElement*> &els, - std::map<MElement*,std::vector<MElement*> > &_elemColumns, - std::map<MElement*,MElement*> &_toFirst ) +static void filterOverlappingElements (std::vector<MLine*> &lines, + std::vector<MElement*> &els, + std::map<MElement*,std::vector<MElement*> > &_elemColumns, + std::map<MElement*,MElement*> &_toFirst ) { std::vector<MElement*> newEls; RTree<MElement*,double,3,double> rtree; + + for (unsigned int i=0;i<lines.size();i++){ + MElement *e = lines[i]; + double _min[3],_max[3]; + MElementBB(e,_min,_max); + rtree.Insert(_min,_max,e); + } + + for (unsigned int i=0;i<els.size();i++){ MElement *e = els[i]; double _min[3],_max[3]; @@ -210,7 +204,7 @@ void filterOverlappingElements (std::vector<MElement*> &els, MElement_Wrapper w(e,_elemColumns[first]); rtree.Search(_min,_max,rtree_callback,&w); if (w._overlap){ - delete e; + // delete e; } else { rtree.Insert(_min,_max,e); @@ -220,3 +214,28 @@ void filterOverlappingElements (std::vector<MElement*> &els, els = newEls; } +// WE SHOULD ADD THE BOUNDARY OF THE DOMAIN IN ORDER TO AVOID +// ELEMENTS THAT ARE OUTSIDE THE DOMAIN --> FIXME + +void filterOverlappingElements (std::vector<MLine*> &bdry, + std::vector<MTriangle*> &blTris, + std::vector<MQuadrangle*>&blQuads, + std::map<MElement*,std::vector<MElement*> > &_elemColumns, + std::map<MElement*,MElement*> &_toFirst) +{ + std::vector<MElement*> vvv; + vvv.insert(vvv.begin(),blTris.begin(),blTris.end()); + vvv.insert(vvv.begin(),blQuads.begin(),blQuads.end()); + Less_Partition lp; + std::sort(vvv.begin(),vvv.end(), lp); + filterOverlappingElements (bdry,vvv,_elemColumns,_toFirst); + filterColumns (vvv,_elemColumns); + blTris.clear(); + blQuads.clear(); + for (unsigned int i=0;i<vvv.size();i++){ + if (vvv[i]->getType() == TYPE_TRI)blTris.push_back((MTriangle*)vvv[i]); + else if (vvv[i]->getType() == TYPE_QUA)blQuads.push_back((MQuadrangle*)vvv[i]); + } + + +} diff --git a/Mesh/filterElements.h b/Mesh/filterElements.h index 60f16ff06a381eeb15843efdfe12a0c770265c0a..bd18e2937c3ab9194522d5bbd0b6c0fc5240c9e6 100644 --- a/Mesh/filterElements.h +++ b/Mesh/filterElements.h @@ -10,19 +10,12 @@ #include <vector> class MElement; -class MPrism; -class MHexahedron; class MTriangle; class MQuadrangle; +class MLine; -void filterOverlappingElements(std::vector<MElement*> &, - std::map<MElement*,std::vector<MElement*> > &_elemColumns, - std::map<MElement*,MElement*> &_toFirst); -void filterOverlappingElements(std::vector<MPrism*> &blPrisms, - std::vector<MHexahedron*>&blHexes, - std::map<MElement*,std::vector<MElement*> > &_elemColumns, - std::map<MElement*,MElement*> &_toFirst); -void filterOverlappingElements(std::vector<MTriangle*> &blTris, +void filterOverlappingElements(std::vector<MLine*> &_lines, + std::vector<MTriangle*> &blTris, std::vector<MQuadrangle*>&blQuads, std::map<MElement*,std::vector<MElement*> > &_elemColumns, std::map<MElement*,MElement*> &_toFirst); diff --git a/Mesh/meshGEdge.cpp b/Mesh/meshGEdge.cpp index 068d23662c7394d172e0d45ba4664998a1972a0e..5330284cc749a191ef843c6ac05fbeef2ffd7397 100644 --- a/Mesh/meshGEdge.cpp +++ b/Mesh/meshGEdge.cpp @@ -78,34 +78,36 @@ static double smoothPrimitive(GEdge *ge, double alpha, static double F_LcB(GEdge *ge, double t) { - BoundaryLayerField *blf = 0; + /* BoundaryLayerField *blf = 0; #if defined(HAVE_ANN) FieldManager *fields = ge->model()->getFields(); Field *bl_field = fields->get(fields->getBoundaryLayerField()); blf = dynamic_cast<BoundaryLayerField*> (bl_field); #endif - + */ GPoint p = ge->point(t); double lc = BGM_MeshSize(ge, t, 0, p.x(), p.y(), p.z()); - if (blf){ + /* if (blf){ double lc2 = (*blf)( p.x(), p.y(), p.z() , ge); // printf("p %g %g lc %g\n",p.x(),p.y(),lc2); lc = std::min(lc, lc2); } + */ return lc; } static double F_Lc(GEdge *ge, double t) { + /* BoundaryLayerField *blf = 0; #if defined(HAVE_ANN) FieldManager *fields = ge->model()->getFields(); Field *bl_field = fields->get(fields->getBoundaryLayerField()); blf = dynamic_cast<BoundaryLayerField*> (bl_field); #endif - + */ GPoint p = ge->point(t); double lc_here; @@ -119,13 +121,13 @@ static double F_Lc(GEdge *ge, double t) lc_here = BGM_MeshSize(ge->getEndVertex(), t, 0, p.x(), p.y(), p.z()); else lc_here = BGM_MeshSize(ge, t, 0, p.x(), p.y(), p.z()); - + /* if (blf){ double lc2 = (*blf)( p.x(), p.y(), p.z() , ge); // printf("p %g %g lc %g\n",p.x(),p.y(),lc2); lc_here = std::min(lc_here, lc2); } - + */ SVector3 der = ge->firstDer(t); const double d = norm(der); @@ -445,7 +447,24 @@ static void filterPoints (GEdge*ge, int nMinimumPoints) } } -void meshGEdge::operator() (GEdge *ge) +static void createPoints ( GVertex *gv, GEdge *ge, BoundaryLayerField *blf , + std::vector<MVertex*>& v, const SVector3 &dir){ + double L = blf->hwall_n; + while (1){ + if (L > blf->thickness) break; + SPoint3 p (gv->x() + dir.x() * L, gv->y() + dir.y() * L, 0.0); + v.push_back(new MEdgeVertex (p.x(), p.y(), p.z(), ge, ge->parFromPoint(p), blf->hfar)); + int ith = v.size() ; + L+= blf->hwall_n * pow (blf->ratio, ith); + // printf("parameter %g length %g\n",ge->parFromPoint(p),L); + } +} + +void addBoundaryLayerPoints (GEdge *ge, + double &t_begin, // may change the left parameter of the interval + double &t_end, // may change the right parameter of the interval + std::vector<MVertex*> &_addBegin, // additional points @ left + std::vector<MVertex*> &_addEnd) // additional points @ right { BoundaryLayerField *blf = 0; #if defined(HAVE_ANN) @@ -454,7 +473,46 @@ void meshGEdge::operator() (GEdge *ge) blf = dynamic_cast<BoundaryLayerField*> (bl_field); if (blf) blf->setupFor1d(ge->tag()); #endif + if (!blf) return; + if (blf->isEdgeBL(ge->tag()))return; + SVector3 dir ( ge->getEndVertex()->x() - ge->getBeginVertex()->x(), + ge->getEndVertex()->y() - ge->getBeginVertex()->y(), + ge->getEndVertex()->z() - ge->getBeginVertex()->z()); + dir.normalize(); + GVertex *gvb = ge->getBeginVertex(); + GVertex *gve = ge->getEndVertex(); + if (blf->isEndNode(gvb->tag())){ + if (ge->geomType() != GEntity::Line){ + Msg::Error ("Boundary layer end point %d should lie on a straight line", gvb->tag()); + return; + } + createPoints (gvb, ge, blf, _addBegin, dir); + if (!_addBegin.empty())_addBegin[_addBegin.size()-1]->getParameter(0,t_begin); + } + if (blf->isEndNode(gve->tag())){ + if (ge->geomType() != GEntity::Line){ + Msg::Error ("Boundary layer end point %d should lie on a straight line", gve->tag()); + return; + } + createPoints (gve, ge, blf, _addEnd, dir * -1.0); + if (!_addEnd.empty())_addEnd[_addEnd.size()-1]->getParameter(0,t_end); + } + + // printf("Edge %d ยง %d %d points added (%g %g)-\n", ge->tag(), _addBegin.size(),_addEnd.size(),t_begin,t_end); +} +void meshGEdge::operator() (GEdge *ge) +{ + /* + BoundaryLayerField *blf = 0; +#if defined(HAVE_ANN) + FieldManager *fields = ge->model()->getFields(); + Field *bl_field = fields->get(fields->getBoundaryLayerField()); + blf = dynamic_cast<BoundaryLayerField*> (bl_field); + if (blf) blf->setupFor1d(ge->tag()); +#endif + */ + ge->model()->setCurrentMeshEntity(ge); // if(ge->geomType() == GEntity::DiscreteCurve) return; @@ -488,6 +546,10 @@ void meshGEdge::operator() (GEdge *ge) double t_begin = bounds.low(); double t_end = bounds.high(); + // if a BL is ending at one of the ends, then create specific points + std::vector<MVertex*> _addBegin, _addEnd; + addBoundaryLayerPoints (ge, t_begin, t_end, _addBegin, _addEnd); + // first compute the length of the curve by integrating one double length; std::vector<IntPoint> Points; @@ -541,7 +603,7 @@ void meshGEdge::operator() (GEdge *ge) SVector3 der = ge->firstDer(pt.t); pt.xp = der.norm(); } - // a = smoothPrimitive(ge, sqrt(CTX::instance()->mesh.smoothRatio), Points); + a = smoothPrimitive(ge, sqrt(CTX::instance()->mesh.smoothRatio), Points); filterMinimumN = ge->minimumMeshSegments() + 1; N = std::max(filterMinimumN, (int)(a + 1.99)); } @@ -620,8 +682,20 @@ void meshGEdge::operator() (GEdge *ge) mesh_vertices.resize(NUMP - 1); } + // Boundary Layer points are added + { + std::vector<MVertex*> vv; + vv.insert(vv.end(), _addBegin.begin(), _addBegin.end()); + vv.insert(vv.end(), mesh_vertices.begin(), mesh_vertices.end()); + for (unsigned int i=0;i<_addEnd.size();i++) + vv.push_back(_addEnd[_addEnd.size()-1-i]); + // vv.insert(vv.end(), _addEnd.rend(), _addEnd.rbegin()); + mesh_vertices = vv; + } + // printf("%ld ----> ", ge->mesh_vertices.size()); - filterPoints (ge, filterMinimumN - 2); + if (_addBegin.empty() && _addEnd.empty()) + filterPoints (ge, filterMinimumN - 2); // printf("%ld \n", ge->mesh_vertices.size()); for(unsigned int i = 0; i < mesh_vertices.size() + 1; i++){ diff --git a/Mesh/meshGFace.cpp b/Mesh/meshGFace.cpp index 4a90b7c24c09082f7dc404ec38d650dd730ca609..450f36d3836982e10707ac7213119613410e8fd2 100644 --- a/Mesh/meshGFace.cpp +++ b/Mesh/meshGFace.cpp @@ -662,8 +662,12 @@ static void modifyInitialMeshForTakingIntoAccountBoundaryLayers(GFace *gf) FILE *ff2 = Fopen ("tato.pos","w"); if(ff2) fprintf(ff2,"View \" \"{\n"); std::set<MVertex*> verts; + + std::vector<MLine*> _lines; + while(ite != edges.end()){ for(unsigned int i = 0; i< (*ite)->lines.size(); i++){ + _lines.push_back((*ite)->lines[i]); MVertex *v1 = (*ite)->lines[i]->getVertex(0); MVertex *v2 = (*ite)->lines[i]->getVertex(1); MEdge dv(v1,v2); @@ -691,6 +695,7 @@ static void modifyInitialMeshForTakingIntoAccountBoundaryLayers(GFace *gf) //avoid convergent errors if (dv2.length() < 0.03 * dv.length())break; MQuadrangle *qq = new MQuadrangle(v11,v21,v22,v12); + qq->setPartition (l+1); myCol.push_back(qq); blQuads.push_back(qq); if(ff2) @@ -732,6 +737,7 @@ static void modifyInitialMeshForTakingIntoAccountBoundaryLayers(GFace *gf) } if (v11 != v12){ MQuadrangle *qq = new MQuadrangle(v11,v12,v22,v21); + qq->setPartition (l+1); myCol.push_back(qq); blQuads.push_back(qq); if(ff2) @@ -743,6 +749,7 @@ static void modifyInitialMeshForTakingIntoAccountBoundaryLayers(GFace *gf) } else { MTriangle *qq = new MTriangle(v,v22,v21); + qq->setPartition (l+1); myCol.push_back(qq); blTris.push_back(qq); if(ff2) @@ -762,7 +769,7 @@ static void modifyInitialMeshForTakingIntoAccountBoundaryLayers(GFace *gf) fclose(ff2); } - // filterOverlappingElements (blTris,blQuads,_columns->_elemColumns,_columns->_toFirst); + filterOverlappingElements (_lines, blTris,blQuads,_columns->_elemColumns,_columns->_toFirst); for (unsigned int i = 0; i < blQuads.size();i++){ addOrRemove(blQuads[i]->getVertex(0),blQuads[i]->getVertex(1),bedges, removed); @@ -803,7 +810,7 @@ static void modifyInitialMeshForTakingIntoAccountBoundaryLayers(GFace *gf) deMeshGFace kil_; kil_(gf); meshGenerator(gf, 0, 0, true , false, &hop); - + gf->quadrangles = blQuads; gf->triangles.insert(gf->triangles.begin(),blTris.begin(),blTris.end()); gf->mesh_vertices.insert(gf->mesh_vertices.begin(),verts.begin(),verts.end()); @@ -1543,8 +1550,9 @@ bool meshGenerator(GFace *gf, int RECUR_ITER, // BDS mesh is passed in order not to recompute local coordinates of // vertices if(algoDelaunay2D(gf) && !onlyInitialMesh){ - if(gf->getMeshingAlgo() == ALGO_2D_FRONTAL) + if(gf->getMeshingAlgo() == ALGO_2D_FRONTAL){ bowyerWatsonFrontal(gf); + } else if(gf->getMeshingAlgo() == ALGO_2D_FRONTAL_QUAD){ bowyerWatsonFrontalLayers(gf,true); } diff --git a/Mesh/meshRefine.cpp b/Mesh/meshRefine.cpp index aa5dbe3f9d01a80ab3c4e670b7a8fe86252e7882..8ebafac03340947d66d3204e8ea323e03b2620c8 100644 --- a/Mesh/meshRefine.cpp +++ b/Mesh/meshRefine.cpp @@ -449,8 +449,8 @@ static void Subdivide(GRegion *gr, bool splitIntoHexas, faceContainer &faceVerti void RefineMesh(GModel *m, bool linear, bool splitIntoQuads, bool splitIntoHexas) { - // splitIntoQuads = true; - // splitIntoHexas = true; + splitIntoQuads = true; + splitIntoHexas = true; Msg::StatusBar(true, "Refining mesh..."); double t1 = Cpu(); diff --git a/benchmarks/2d/BL1.geo b/benchmarks/2d/BL1.geo new file mode 100755 index 0000000000000000000000000000000000000000..6030cc9c59a386e65f686756c820b23ad87356c3 --- /dev/null +++ b/benchmarks/2d/BL1.geo @@ -0,0 +1,54 @@ +Mesh.CharacteristicLengthFromCurvature=1; +Mesh.MinimumCirclePoints=20; +l = .2; +//+ +Point(1) = {-1.1, -0.3, 0, l}; +//+ +Point(2) = {-0.3, -0, 0, l}; +//+ +Point(3) = {1, -0.3, 0, l}; +//+ +Point(4) = {-0.3, -0.6, 0, l}; +//+ +Point(5) = {0.7, -0.2, 0, l}; +//+ +Point(6) = {0.7, -0.4, 0, l}; +//+ +Spline(1) = {3, 5, 2, 1, 4, 6, 3}; +//+ +Point(7) = {-1.4, 0.5, 0, l}; +//+ +Point(8) = {-1.4, -1.1, 0, l}; +//+ +Point(9) = {1.4, -1.1, 0, l}; +//+ +Point(10) = {1.4, 0.5, 0, l}; +//+ +Line(2) = {7, 10}; +//+ +Line(3) = {9, 10}; +//+ +Line(4) = {9, 8}; +//+ +Line(5) = {8, 7}; +//+ +Line Loop(6) = {2, -3, 4, 5}; +//+ +Line Loop(7) = {1}; +//+ +Plane Surface(8) = {6, 7}; +//+ +Field[1] = BoundaryLayer; +//+ +Field[1].EdgesList = {1}; +//+ +Field[1].hfar = 0.1; +//+ +Field[1].hwall_n = 0.01; +//+ +Field[1].thickness = 0.1; +//+ +BoundaryLayer Field = 1; + +//+ +Field[1].ratio = 1.4; diff --git a/benchmarks/2d/BL2.geo b/benchmarks/2d/BL2.geo new file mode 100644 index 0000000000000000000000000000000000000000..49e1815d23799a7573f49c06dc2ebcee135993ca --- /dev/null +++ b/benchmarks/2d/BL2.geo @@ -0,0 +1,63 @@ +Mesh.CharacteristicLengthFromCurvature=1; +Mesh.MinimumCirclePoints=20; +l = .2; +//+ +Point(1) = {-1.1, -0.3, 0, l}; +//+ +Point(2) = {-0.3, -0, 0, l}; +//+ +Point(3) = {1, -0.3, 0, l}; +//+ +Point(4) = {-0.3, -0.6, 0, l}; +//+ +Point(5) = {0.7, -0.2, 0, l}; +//+ +Point(6) = {0.7, -0.4, 0, l}; +//+ +Spline(1) = {1, 4, 6, 3}; +Spline(11) = {3 , 5 , 2 , 1}; +//+ +Point(7) = {-1.4, .5, 0, l}; +//+ +Point(8) = {-1.4, -1.1, 0, l}; +//+ +Point(9) = {3.4, -1.1, 0, l}; +//+ +Point(10) = {3.4, .5, 0, l}; +//+ +Line(2) = {7, 10}; +//+ +Line(3) = {9, 10}; +//+ +Line(4) = {9, 8}; +//+ +Line(5) = {8, 7}; +//+ +Line Loop(6) = {2, -3, 4, 5}; +//+ +Line Loop(7) = {1, 11}; +//+ +Plane Surface(8) = {6, 7}; +//+ +Field[1] = BoundaryLayer; +//+ +Field[1].EdgesList = {1, 11, 9}; +//+ +Field[1].hfar = 0.1; +//+ +Field[1].hwall_n = 0.01; +//+ +Field[1].thickness = 0.1; +//+ +BoundaryLayer Field = 1; + +//+ +Field[1].ratio = 1.4; +//+ +Point(11) = {2.2, -0.3, 0, l}; +//+ +Line(9) = {3, 11}; +Line {9} In Surface {8};//+ +Field[1].FanNodesList = {1}; +//+ +Field[1].Quads = 1; diff --git a/benchmarks/2d/BL3.geo b/benchmarks/2d/BL3.geo new file mode 100644 index 0000000000000000000000000000000000000000..71c6a54732ef134310f3192cbb0948bff2bb1721 --- /dev/null +++ b/benchmarks/2d/BL3.geo @@ -0,0 +1,84 @@ +Mesh.CharacteristicLengthExtendFromBoundary = 0; +Mesh.CharacteristicLengthMin = 0.1; +Mesh.CharacteristicLengthMax = 0.1; +//+ +Point(1) = {-1.7, -0.3, 0, .1}; +//+ +Point(2) = {-1.2, -0, 0, .1}; +//+ +Point(3) = {-0.5, -0.3, 0, .1}; +//+ +Point(4) = {-0.4, -0.7, 0, .1}; +//+ +Point(5) = {-0.8, -0.8, 0, .1}; +//+ +Point(6) = {-1.2, -0.5, 0, .1}; +//+ +Point(7) = {-1.8, -0.5, 0, .1}; +//+ +Point(8) = {-1.1, 0.6, 0, .1}; +//+ +Point(9) = {-0.5, 0.7, 0, .1}; +//+ +Point(10) = {-0.1, 0.2, 0, .1}; +//+ +Point(11) = {-0.3, -0.1, 0, .1}; +//+ +Point(12) = {-0.7, 0.2, 0, .1}; +//+ +Point(13) = {-1.1, 0.4, 0, 1.0}; +//+ +Point(14) = {-1.5, 0.5, 0, .1}; +//+ +Point(15) = {-2.3, 1.1, 0, .1}; +//+ +Point(16) = {-2.3, -1, 0, .1}; +//+ +Point(17) = {0.7, -1, 0, .1}; +//+ +Point(18) = {0.5, 1.1, 0, .1}; +//+ +Line(1) = {15, 16}; +//+ +Line(2) = {16, 17}; +//+ +Line(3) = {17, 18}; +//+ +Line(4) = {18, 15}; +//+ +Spline(5) = {14, 8, 9, 10, 11, 12, 13, 14}; +//+ +Spline(6) = {2, 3, 4, 5, 6, 7, 1, 2}; +//+ +Field[1] = BoundaryLayer; +//+ +Field[1].EdgesList = {5, 6, 1}; +//+ +Field[1].hfar = 0.1; +//+ +Field[1].hwall_n = 0.001; +//+ +Field[1].ratio = 1.4; +//+ +Field[1].thickness = 0.38; +BoundaryLayer Field = 1; +//+ +Line Loop(7) = {1, 2, 3, 4}; +//+ +Line Loop(8) = {5}; +//+ +Line Loop(9) = {6}; +//+ +Plane Surface(10) = {7, 8, 9}; +//+ +Characteristic Length {1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14} = 0.1; +//+ +Field[1].FanNodesList = {14}; +//+ +Characteristic Length {17, 16, 5, 4, 6, 7, 3, 1, 11, 2, 10, 12, 13, 14, 8, 9, 15, 18} = 0.1; +//+ +Field[1].Quads = 1; +//+ +//Field[1].thickness = 1; +//+ +Field[1].NodesList = {15, 16}; diff --git a/benchmarks/3d/hex.geo b/benchmarks/3d/hex.geo index a838d0ff2d5e56d4bbc774f154f4bb518fdc954c..35c542e57b029f9e33db3acbf0df19cf4c9a2a5c 100644 --- a/benchmarks/3d/hex.geo +++ b/benchmarks/3d/hex.geo @@ -4,7 +4,7 @@ lc = 0.3; // example of a purely hexahedral mesh using only transfinite // mesh constraints z=1; -deform=0.0; +deform=0; Point(1) = {-2-deform,0,0,lc}; Point(2) = {-1,0,0,lc}; @@ -40,8 +40,8 @@ Line Loop(24) = {6,-12,3,10}; Ruled Surface(25) = {24}; Surface Loop(1) = {17,-25,-23,-21,19,15}; Volume(1) = {1}; -Transfinite Line{1:4,6:9} = 20; -Transfinite Line{10:13} = 20; +Transfinite Line{1:4,6:9} = 2; +Transfinite Line{10:13} = 2; Transfinite Surface {15} = {1,2,3,4}; Transfinite Surface {17} = {5,6,7,8}; diff --git a/contrib/HighOrderMeshOptimizer/OptHomFastCurving.cpp b/contrib/HighOrderMeshOptimizer/OptHomFastCurving.cpp index 34c59b566c715c494a9199681e3f1942090e5e51..f71e14d54207d47cb6ed638f2d376061f6eb3178 100644 --- a/contrib/HighOrderMeshOptimizer/OptHomFastCurving.cpp +++ b/contrib/HighOrderMeshOptimizer/OptHomFastCurving.cpp @@ -308,9 +308,10 @@ bool getTopPrimVertices(std::map<MVertex*, std::vector<MElement *> > &vertex2ele topPrimVert = std::vector<MVertex*>(nbVert); for(int i = 0; i < nbVert; i++) { if (blc && (blc->size() > 1)) { // Is there BL data? - const BoundaryLayerData &c = blc->getColumn(baseVert[i], baseBnd); - if (c._column.size() == 0) return false; // Give up element if column not found - topPrimVert[i] = *(c._column.end()-2); + return false; + // const BoundaryLayerData &c = blc->getColumn(baseVert[i], baseBnd); + // if (c._column.size() == 0) return false; // Give up element if column not found + // topPrimVert[i] = *(c._column.end()-2); } else { // No BL data, look for columns of vertices std::map<MVertex*, SVector3>::const_iterator itNorm = normVert.find(baseVert[i]); @@ -553,12 +554,12 @@ void HighOrderMeshFastCurving(GModel *gm, FastCurvingParameters &p) 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 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