From dff2fbfc6e3f31c2bb2fa93e400c26dd3472a175 Mon Sep 17 00:00:00 2001 From: Jean-Francois Remacle <jean-francois.remacle@uclouvain.be> Date: Mon, 10 Oct 2011 15:25:00 +0000 Subject: [PATCH] ooops : forgot 3 files --- Mesh/meshGFaceBoundaryLayers.cpp | 341 +++++++++++++++++++++++++++++++ Mesh/meshGFaceBoundaryLayers.h | 89 ++++++++ 2 files changed, 430 insertions(+) create mode 100644 Mesh/meshGFaceBoundaryLayers.cpp create mode 100644 Mesh/meshGFaceBoundaryLayers.h diff --git a/Mesh/meshGFaceBoundaryLayers.cpp b/Mesh/meshGFaceBoundaryLayers.cpp new file mode 100644 index 0000000000..87b6e5ba0b --- /dev/null +++ b/Mesh/meshGFaceBoundaryLayers.cpp @@ -0,0 +1,341 @@ +#include "GModel.h" +#include "GFace.h" +#include "MVertex.h" +#include "MLine.h" +#include "MTriangle.h" +#include "MEdge.h" +#include "meshGFaceBoundaryLayers.h" +#include "Field.h" +/* + | + | / + +--------x / + \ + \ + \ + +*/ + + +SVector3 interiorNormal (SPoint2 p1, SPoint2 p2, SPoint2 p3){ + + SVector3 ez (0,0,1); + SVector3 d (p1.x()-p2.x(),p1.y()-p2.y(),0); + SVector3 h (p3.x()-0.5*(p2.x()+p1.x()),p3.y()-0.5*(p2.y()+p1.y()),0); + SVector3 n = crossprod(d,ez); + n.normalize(); + // printf("%g %g\n",n.x(),n.y()); + if (dot(n,h) > 0)return n; + 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<3;i++){ + for (int l=0;l<3;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]; +} + +BoundaryLayerColumns* buidAdditionalPoints2D (GFace *gf, double _treshold) { + + FieldManager *fields = gf->model()->getFields(); + if(fields->background_field <= 0){ + return 0; + } + Field *bl_field = fields->get(fields->background_field); + BoundaryLayerField *blf = dynamic_cast<BoundaryLayerField*> (bl_field); + + if (!blf)return 0; + + + BoundaryLayerColumns * _columns = new BoundaryLayerColumns; + + // assume a field that i) gives us the closest point on one of the BL components + // ii) Gives us mesh sizes in the 3 directions. + + // build vertex to vertex connexions + std::list<GEdge*> edges = gf->edges(); + std::list<GEdge*>::iterator ite = edges.begin(); + std::set<MVertex*> _vertices; + while(ite != edges.end()){ + for(unsigned int i = 0; i< (*ite)->lines.size(); i++){ + MVertex *v1 = (*ite)->lines[i]->getVertex(0); + MVertex *v2 = (*ite)->lines[i]->getVertex(1); + _columns->_non_manifold_edges.insert(std::make_pair(v1,v2)); + _columns->_non_manifold_edges.insert(std::make_pair(v2,v1)); + _vertices.insert(v1); + _vertices.insert(v2); + } + ++ite; + } + + // printf("%d boundary points\n",_vertices.size()); + + // assume that the initial mesh has been created i.e. that there exist + // triangles inside the domain. Triangles are used to define + // exterior normals + std::multimap<MEdge,SVector3,Less_Edge> _normals; + for (int i=0;i<gf->triangles.size();i++){ + SPoint2 p0,p1,p2; + MVertex *v0 = gf->triangles[i]->getVertex(0); + MVertex *v1 = gf->triangles[i]->getVertex(1); + MVertex *v2 = gf->triangles[i]->getVertex(2); + reparamMeshEdgeOnFace(v0, v1, gf, p0, p1); + reparamMeshEdgeOnFace(v0, v2, gf, p0, p2); + + MEdge me01(v0,v1); + SVector3 v01 = interiorNormal (p0,p1,p2); + _normals.insert(std::make_pair(me01,v01)); + + MEdge me02(v0,v2); + SVector3 v02 = interiorNormal (p0,p2,p1); + _normals.insert(std::make_pair(me02,v02)); + + MEdge me21(v2,v1); + SVector3 v21 = interiorNormal (p2,p1,p0); + _normals.insert(std::make_pair(me21,v21)); + } + + // for all boundry points + for (std::set<MVertex*>::iterator it = _vertices.begin(); it != _vertices.end() ; ++it){ + std::vector<MVertex*> _connections; + std::vector<SVector3> _dirs; + double LL; + for ( std::multimap<MVertex*,MVertex*> :: iterator itm = _columns->_non_manifold_edges.lower_bound(*it); + itm != _columns->_non_manifold_edges.upper_bound(*it); ++itm) + _connections.push_back (itm->second); + // STANDARD CASE, one vertex connected to two neighboring vertices + // printf("point %d %d edegs connected\n",(*it)->getNum(),_connections.size()); + if (_connections.size() == 2){ + MEdge e1 (*it,_connections[0]); + MEdge e2 (*it,_connections[1]); + LL = 0.5 * (e1.length() + e2.length()); + std::vector<SVector3> N1,N2; + for ( std::multimap<MEdge,SVector3,Less_Edge> :: iterator itm = _normals.lower_bound(e1); + itm != _normals.upper_bound(e1); ++itm) N1.push_back(itm->second); + for ( std::multimap<MEdge,SVector3,Less_Edge> :: iterator itm = _normals.lower_bound(e2); + itm != _normals.upper_bound(e2); ++itm) N2.push_back(itm->second); + // STANDARD CASE : ONLY ONE SIDE FOR THE BL + double LL; + if (N1.size() == 1 && N2.size() == 1){ + // IF THE ANGLE IS GREATER THAN THRESHOLD, ADD DIRECTIONS !! + double angle = computeAngle (gf,e1,e2,N1[0],N2[0]); + + if (angle < _treshold /*&& angle > - _treshold*/){ + SVector3 x = N1[0]*1.01+N2[0]; + x.normalize(); + _dirs.push_back(x); + } + else if (angle >= _treshold){ + int fanSize = angle / _treshold; + printf("ONE FAN HAS BEEN CREATED : %d %d %d %d ANGLE = %g | %g %g %g %g\n",e1.getVertex(0)->getNum(), + e1.getVertex(1)->getNum(),e2.getVertex(0)->getNum(),e2.getVertex(1)->getNum(), + angle/M_PI*180,N1[0].x(),N1[0].y(),N2[0].x(),N2[0].y()); + // if the angle is greater than PI, than reverse the sense + double alpha1 = atan2(N1[0].y(),N1[0].x()); + double alpha2 = atan2(N2[0].y(),N2[0].x()); + double AMAX = std::max(alpha1,alpha2); + double AMIN = std::min(alpha1,alpha2); + MEdge ee[2]; + if (alpha1 > alpha2){ + // _dirs.push_back(N2[0]); + // _dirs.push_back(N1[0]); + ee[0] = e2;ee[1] = e1; + // printf("reversing the first and the last normal %g %g\n",alpha2,alpha1); + } + else { + // _dirs.push_back(N1[0]); + // _dirs.push_back(N2[0]); + ee[0] = e1;ee[1] = e2; + // printf("the first and the last normal are ok %g %g\n",alpha1,alpha2); + } + if ( AMAX - AMIN >= M_PI){ + double temp = AMAX; + AMAX = AMIN + 2*M_PI; + AMIN = temp; + // printf("wrong part of the quadrant taken %g %g\n",AMIN,AMAX); + // fanSize = 0; + MEdge eee0 = ee[0]; + ee[0] = ee[1];ee[1] = eee0; + } + _columns->addFan (*it,ee[0],ee[1],true); + + for (int i=-1; i<=fanSize; i++){ + double t = (double)(i+1)/ (fanSize+1); + double alpha = t * AMAX + (1.-t)* AMIN; + // printf("%d %g %g %g %g\n",i,alpha,alpha1,alpha2,alpha2-alpha1); + SVector3 x (cos(alpha),sin(alpha),0); + x.normalize(); + _dirs.push_back(x); + } + } + } + } + + // now create the BL points + for (int DIR=0;DIR<_dirs.size();DIR++){ + SPoint2 p; + SVector3 n = _dirs[DIR]; + + + // < ------------------------------- > // + // N = X(p0+ e n) - X(p0) // + // = e * (dX/du n_u + dX/dv n_v) // + // < ------------------------------- > // + + MVertex *current = *it; + reparamMeshVertexOnFace(current,gf,p); + + int nbCol = 100; + 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; + while(1){ + + SMetric3 m; + double metric[3]; + double l; + (*bl_field)(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-8 * n.x(), + p.y() + 1.e-8 * 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 (_dirs.size() > 1) printf("l = %g metric = %g %g %g dim %d tag %d \n",l,metric[0],metric[1],metric[2],current->onWhat()->dim(),current->onWhat()->tag()); + // printf("%g %g\n",l,LL); + if (l >= blf->hfar){ + // printf("stopping %g %g\n",l,LL); + break; + } + // printf("%g %g %g \n",current->x(),current->y(),blf->current_distance); + if (blf->current_closest != catt || blf -> current_distance < _current_distance){ + SVector3 aaa (_close- blf->_closest_point); + if (aaa.norm() > 8*blf->hwall_n || blf -> current_distance < _current_distance){ + printf("reaching the skelton %d\n",_column.size()); + delete _column[_column.size()-1]; + _column.erase(--_column.end()); + _metrics.erase(--_metrics.end()); + if (_column.size()){ + delete _column[_column.size()-1]; + _column.erase(--_column.end()); + _metrics.erase(--_metrics.end()); + } + 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()); + _current->bl_data = new MVertexBoundaryLayerData; + current = _current; + _column.push_back(current); + // printf("pnew %g %g new point %g %g n %g %g\n",pnew.x(),pnew.y(),gp.x(),gp.y(),n.x(),n.y()); + _metrics.push_back(m); + // const double l = n[0]*m(0,0) +; + if (_column.size() > nbCol)break; // FIXME + p = pnew; + } + _columns->addColumn(*it, _column, _metrics); + } + } + // HERE WE SHOULD FILTER THE POINTS IN ORDER NOT TO HAVE POINTS THAT ARE TOO CLOSE + + // DEBUG STUFF + + FILE *f = fopen ("test.pos","w"); + 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 (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 _columns; +} + + +void BoundaryLayerColumns::filterPoints() { + std::map<MVertex*,MVertex*> tooclose; +} diff --git a/Mesh/meshGFaceBoundaryLayers.h b/Mesh/meshGFaceBoundaryLayers.h new file mode 100644 index 0000000000..8bf4a99581 --- /dev/null +++ b/Mesh/meshGFaceBoundaryLayers.h @@ -0,0 +1,89 @@ +#ifndef _MESHGFACE_BNDRYLR_ +#define _MESHGFACE_BNDRYLR_ + +#include "STensor3.h" +#include "MEdge.h" +#include <map> +#include <set> +class Field; +class GFace; +struct BoundaryLayerData +{ + BoundaryLayerData (std::vector<MVertex*> column, + std::vector<SMetric3> metrics) + : _column(column),_metrics(metrics) + { + + } + std::vector<MVertex*> _column; + std::vector<SMetric3> _metrics; +}; + +struct BoundaryLayerFan +{ + MEdge _e1, _e2; + bool sense; + BoundaryLayerFan (MEdge e1, MEdge e2 , bool s = true) + : _e1(e1),_e2(e2) , sense (s) + {} +}; + +class BoundaryLayerColumns +{ + std::multimap<MVertex*,BoundaryLayerData> _data; + std::map<MVertex*,BoundaryLayerFan> _fans; +public: + typedef std::multimap<MVertex*,BoundaryLayerData>::iterator iter; + typedef std::map<MVertex*,BoundaryLayerFan>::iterator iterf; + std::multimap<MVertex*,MVertex*> _non_manifold_edges; + iter begin() {return _data.begin();} + iter end() {return _data.end();} + iterf beginf() {return _fans.begin();} + iterf endf() {return _fans.end();} + BoundaryLayerColumns () + { + } + inline void addColumn (MVertex* v, + std::vector<MVertex*> _column, + std::vector<SMetric3> _metrics){ + _data.insert (std::make_pair(v,BoundaryLayerData(_column,_metrics))); + } + inline void addFan (MVertex *v, MEdge e1, MEdge e2, bool s){ + _fans.insert(std::make_pair(v,BoundaryLayerFan(e1,e2,s))); + } + + inline const BoundaryLayerData & getColumn ( MVertex *v, MEdge e ){ + std::map<MVertex*,BoundaryLayerFan>::const_iterator it = _fans.find(v); + int N = getNbColumns (v) ; + if (N == 1) return getColumn(v,0); + Equal_Edge aaa; + if (it != _fans.end()){ + if (aaa(it->second._e1,e)) + return getColumn ( v, 0 ); + else + return getColumn ( v, N-1 ); + } + else printf("ooops\n"); + } + + + inline int getNbColumns (MVertex *v) { + return _data.count (v); + } + inline const BoundaryLayerData & getColumn ( MVertex *v, int iColumn ){ + int count = 0; + for ( std::multimap<MVertex*,BoundaryLayerData> :: iterator itm = _data.lower_bound(v); + itm != _data.upper_bound(v); ++itm) + { + if (count++ == iColumn) return itm->second; + } + } + void filterPoints(); +}; + + +BoundaryLayerColumns * buidAdditionalPoints2D (GFace *gf, double _angle) ; +void buildMeshMetric(GFace *gf, double *uv, SMetric3 &m, double metric[3]); + + +#endif -- GitLab